Есть ли способ АВТОМАТИЧЕСКОГО отслеживания изменения Навигационного свойства для внешнего ключа при ДОБАВЛЕНИИ новых данных?
Возьмём самый простой пример.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int CompanyId { get; set; } //внешний ключ
public Company Company { get; set; } // навигационное свойство
}
using (ApplicationContext db = new ApplicationContext())
{
var company = db.Companies.First();
try
{
User tom = new User { Name = "Tom", Company = company };
db.Users.Add(tom);
db.SaveChanges();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Допустим, что после чтения данных из БД company= db.Companies.First(), кто-то ПОМЕНЯЛ название компании.
И тогда при выполнении кода
User tom = new User { Name = "Tom", Company = company };
db.Users.Add(tom);
db.SaveChanges();
никак не отслеживается, что company ПОМЕНЯЛАСЬ!
Есть ли способ АВТОМАТИЧЕСКОГО отслеживания изменились ли данные в таблице Company?
Что-то на подобие атрибутов [Timestamp] и [ConcurrencyCheck]?
Или каждый раз придётся самому проверять все навигационные свойства что они изменились?
Как правильно делать это на практике? В больших БД.
Ответы (1 шт):
Можно использовать повышенный уровень изоляции транзакций.
В этом случае другие транзакции не смогут вклиниться между нашими First и SaveChanges.
using (var db = new ApplicationContext())
{
var tran = db.Database.BeginTransaction(IsolationLevel.Serializable);
var company = db.Companies.First(c => c.Name == "A");
try
{
User tom = new User { Name = "Tom", Company = company };
db.Users.Add(tom);
db.SaveChanges();
tran.Commit();
}
catch (Exception ex)
{
tran.Rollback();
MessageBox.Show(ex.Message);
}
}
Оправдано ли это - я не уверен. Ведь название компании всё равно может быть изменено уже после выполнения этого кода. Конечно, где-то в истории (если она ведётся) могут остаться правильные записи.
Чистый EF Core не позволяет делать вставки с условиями на стороне сервера.
Я советую посмотреть на ORM linq2db. Она позволяет такие инсёрты.
Понимаю, понимаю... Перейти на другую (правильную) ОРМ (вместо кривой) - это немыслимое дело. Но тогда хотя бы используйте расширение
linq2db.EntityFrameworkCore
. Оно включено в официальный список EF Core Tools & Extensions.