下面是一個使用EF5代碼優先方法在其最簡單的形式的情況:與實體框架刪除主體時處理相關實體5
public abstract class EntityBase<PK>
{
public PK ID { get; set; }
}
public class Country : EntityBase<string>
{
public string Name { get; set; }
}
public class Address : EntityBase<int>
{
[Required]
public string CountryID { get; set; }
public Country Country { get; set; }
// ... other address properties ...
}
Address
和Country
之間的一個一對多的關係設置了無級聯刪除像這樣:
modelBuilder.Entity<Address>()
.HasRequired(a => a.Country)
.WithMany()
.HasForeignKey(a => a.CountryID)
.WillCascadeOnDelete(false);
最後,我有調用SaveChanges
底層的DbContext上原子提交數據更改的CRUD方法的通用基礎repository類。例如: -
public class EFRepository<T, PK> : IRepository<T, PK> where T : EntityBase<PK>
{
//
// ... other methods ...
//
public virtual void Delete(T instance)
{
// ... trigger validations, write to log, etc...
_dbContext.Set<T>().Remove(instance);
try
{
_dbContext.SaveChanges();
}
catch(Exception ex)
{
// ... handle the error ...
}
}
}
第1部分:
場景:
var countryRepo = new EFRepository<Country>();
var country = countryRepo.Save(new Country() { ID="??", Name="Test Country" });
var addressRepo = new EFRepository<Address>();
var address = addressRepo.Save(new Address() { Country=country });
countryRepo.Delete(country);
將失敗,由於依賴Address
存在。然而,之後地址結尾爲空,因爲CountryID
無效,因爲Address.CountryID
是必需的,因此後續的SaveChanges
調用會引發驗證異常,除非地址已分離。
我預計,當一個對象被刪除,EF5將是足夠聰明的,先檢查是否像上面的,並沒有找到任何任何級聯刪除約束,然後進行刪除數據。但恰恰相反,情況似乎如此。
這是正常行爲還是我做錯了什麼?
第2部分:
繼失敗SaveChanges
電話,有些Addresses
現在在我的DbContext無效狀態,需要恢復到原來的值。當然,我可以一直做下去明確通過創建專門的倉庫類和壓倒一切的Delete
每個實體類型(Country
,State
,Order
等),但它的氣味大的時間。我寧願寫一些通用代碼,以便在撥打失敗的SaveChanges
電話後正常恢復相關實體。
這將需要詢問DbContext以獲取實體(例如Country
)爲主體的所有關係,而不管其類別是否定義到相關實體的導航屬性。
E.g. Country
沒有Addresses
屬性,所以我需要以某種方式在DbContext中找到Country
和Address
之間的一對多關係的定義,並使用它將所有相關的Addresses
恢復爲其原始值。
這可能嗎?