在以前的EF版本中,我可以使用以下代碼來實現識別關係:

public class Child
{
    [Key, Column(Order = 1)]
    public virtual int Id { get; set; }

    [Key, Column(Order = 2)]
    public virtual int ParentId { get; set; }
    public virtual Parent Parent { get; set; }
}

需要像這樣輕鬆地從集合中刪除一個孩子:

var parent = _context.Parents.First();
var child = parent.Children.First();

parent.Children.Remove(child);

_context.SaveChanges();

該方法在http://www.kianryan.co.uk/2013/03/orphaned-child/ (方法#2)中描述。

但在EF7中,此代碼在創建遷移時拋出異常:

執行解析操作時拋出異常。有關詳細信息,請參閱InnerException。 --->實體類型'Child'具有使用數據註釋定義的複合主鍵。要設置複合主鍵,請使用fluent API。

我還嘗試使用FluentAPI,如下面的代碼中如何定義嵌套識別關係實體框架代碼中所述:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Parent>()
            .HasMany(p => p.Children)
            .WithOne(c => c.Parent);

        modelBuilder.Entity<Child>()
            .HasKey(c => new {c.Id, c.ParentId});

        base.OnModelCreating(modelBuilder);
    }

這種方法允許成功生成遷移,但是當我嘗試從Children集合中刪除子項時,我遇到以下異常:

System.InvalidOperationException:實體類型“Parent”和“Child”之間的關聯已被切斷,但此關係的外鍵不能設置為null。如果應刪除依賴實體,則設置關係以使用級聯刪除。

但我不想使用級聯刪除,我想使用識別關係!

請幫助我理解我做錯了什麼。謝謝!

一般承認的答案

在刪除時使用級聯,因為這是它用於:

modelBuilder.Entity<Parent>()
    .HasMany(p => p.Children)
    .WithOne(c => c.Parent);
    .WillCascadeOnDelete(true);

https://msdn.microsoft.com/en-gb/data/jj591620.aspx


熱門答案

萬一有人看到這個錯誤,讓我告訴你我是如何解決我的:

當您進行更新時,在EF上您需要首先查詢數據庫並獲取數據模型,然後將Domain層模型與您的更改映射到它(基本上將字段複製到數據上),最後調用DBContext更新方法,然後保存更改。

我的問題是我的模型(不是數據模型,域模型)上也有子對象。

所以這是數據層模型(例如):

public class Parent
{
   public int ChildId {get; set; }

   [ForeignKey("ChildId")]
   public virtual Child Child { get; set; }
}

以下是域層模型應該如何:

public class Parent
    {
        public int ChildId { get; set; }
        //public Child Child { get; set; }  // this caused the error, keep reading if you want to know more.
    }

當我看到錯誤時,我一直在使用Autofac的運行時映射器將域層模型的屬性映射到數據層模型。但是,域層模型中的子項為null,因此它會使數據層無效,從而導致錯誤:

“實體類型'Parent'和'Child'之間的關聯已被切斷,但此關係的外鍵不能設置為null。如果應刪除依賴實體,則設置關係以使用級聯刪除。”


順便說一句,在db上下文類中,我定義了以下關係:

modelBuilder.Entity<Parent>()
   .HasOne(a => a.Child)
   .WithMany()
   .HasForeignKey(p => p.ChildId)
   .OnDelete(DeleteBehavior.Restrict);

它正在發揮作用。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow