0

我有一個關於將實體框架4.1 CF中的子實體添加到根實體的問題。實體框架代碼優先 - 通過聚合根添加1:很多

考慮下面的基礎設施實體基類和兩個波蘇斯:

public abstract class EntityBase<TKeyDataType> 
{ 
    [Key] 
    public TKeyDataType Id { get; set; } 

    // Equality methods ommitted for brevity... 
} 

public class Foo : EntityBase<int>, IAggregateRoot 
{ 
    public string Foo1 { get; set; } 

    public virtual ICollection<FooSibling> Siblings { get; set; } 
} 

public class FooSibling : EntityBase<int> 
{ 
    public string SiblingPropFoo { get; set; } 

    public int FooId { get; set; } 
    public Foo Foo { get; set; } 
} 

注意Foo工具IAggregateRoot(只是一個空洞的接口 - 把它作爲元數據的上下文中的「關於數據的數據」)。

到目前爲止,這麼好。如果我運行它,EF使用適當的1:多關係創建數據庫。

唯一的一口流利的映射我有兩個實體:

modelBuilder.Entity<Foo>() 
      .HasMany(x => x.Siblings) 
      .WithRequired(x=>x.Foo) 
      .WillCascadeOnDelete(true); 

沒有FooSibling沒有Foo。吹掉一個Foo,你吹走所有的兄弟姐妹。這件作品。

的問題是增加FooSiblings POCO到富POCO的時候,我都用獨特的負數如本服務的方法:

public ResponseBase UpdateBy(RequestBase<Foo> request) 
{ 
    ResponseBase response = new ResponseBase(); 
    try 
    { 
     Foo foo = FooRepository.FirstOrDefault(x => x.Id == request.Entity.Id); 

     // Dummy adds to test associations. 
     // These come back on the Foo inside the request, but I'm explicitly putting them here 
     // for the purpose of this question. 

     request.Entity.Siblings.Add(new FooSibling() { Id = -2, SiblingPropFoo = "Prop1", SiblingPropFoo2 = "Prop2" }); 
     request.Entity.Siblings.Add(new FooSibling() { Id = -1, SiblingPropFoo = "Prop1", SiblingPropFoo2 = "Prop2" }); 

     // Update Foo's scalars and children (mapping is Foo->Foo) 
     foo = AutoMapper.Mapper.Map(request.Entity, foo); 

     UnitOfWork.Commit(); 
     response.Success = true; 
    } 
    catch (Exception e) 
    { 
     response.Success = false; 
     response.Message = e.Message; 
    } 
    return response; 
} 

一旦UnitofWork.Commit()被稱爲(它只是調用上下文的SaveChanges - 這裏沒有魔法),一切都很好...

但是,如果我不使用獨特的負數一樣,只是嘗試設置其母公司,像這樣:

request.Entity.Siblings.Add(new FooSibling() { Foo = foo, SiblingPropFoo = "Prop1", SiblingPropFoo2 = "Prop2" }); 
request.Entity.Siblings.Add(new FooSibling() { Foo = foo, SiblingPropFoo = "Prop1", SiblingPropFoo2 = "Prop2" }); 

只有一個持久化到數據庫。

我知道做到這一點,而無需使用負數唯一的另一種方法是直接在服務方法使用FooSiblings DbSet:

IRepository<FooSibling> siblingRepo = new CookieCutterEntityFrameworkRepository<FooSibling>(UnitOfWork); 
siblingRepo.Insert(new FooSibling() { FooId = foo, .... }); 

我18.11存儲庫抽象所有DbSet東西,等

但是......爲了清晰起見,剝離所有抽象和泛型伏都,問題真的歸結爲是否有方法更新我的Foo POCO(根實體)並通過一個DbSet添加新的兄弟而不使用負數? (使用純的DbContext沒有抽象)

參考:

// This works (using multiple DbSets/Repositories always make life easier...) 
Ctx.Foos.Update(foo); 
Ctx.FooSiblings.Add(new FooSibling() { Foo = foo, ... }); 
Ctx.FooSiblings.Add(new FooSibling() { Foo = foo, ... }); 
Ctx.SaveChanges(); 

// This works too (using negative number trick - foo scalar properties get 
// updated and the siblings get persisted to the database properly). 
foo.Siblings.Add(new FooSibling() { Id = -2, ....}); 
foo.Siblings.Add(new FooSibling() { Id = -1, ....}); 
Ctx.Foos.Update(foo); 
Ctx.SaveChanges(); 

// This doesn't work (but it's what I'm striving for to drive everything off the root). 
foo.Siblings.Add(new FooSibling() { Foo = foo }); 
foo.Siblings.Add(new FooSibling() { Foo = foo }); 
Ctx.Foos.Update(foo); 
Ctx.SaveChanges(); 

在最後一種情況下(非工作情況下),我努力將其配置在它拿起任何變化的時尚Foo POCO本身。

我試過關閉代理服務器。而且,按照這種設置方式,上下文仍然處於整個HTTP請求生命週期的範圍內。

如果不可能,您會提出什麼建議?

回答

2

如果我正確地閱讀這個問題,可以通過dbcontext或objectcontext預期問題。

FIrst我想看看你的最後一組例子..沒有抽象。將圖形附加到上下文時,圖形中的所有內容都將附加爲「未更改」。期。上下文並不關心在上下文有任何知識的情況下,如何在根上添加或附加「子」(例如,兄弟姐妹)。如果foo已經被上下文所知,然後你添加,那麼上下文知道你如何做鏈接..你說「ADD」,所以它將它們標記爲Added,並且它們將被插入。即使根目錄是不是新的。您必須將其狀態更改爲「未更改」。但在你的情況下,你正在採取一個不連貫的圖並附加它,所以圖中的每一個都被認爲是不變的。您必須明確將每個同級的狀態更改爲SaveChanges需要注意的事項。

現在到您的存儲庫。我不知道wtf是與負數。 :)我沒有時間去實驗。 (好奇的是如何欺騙savechanges,但它是一個臭ha :))這取決於你的FooRepository查詢背後發生了什麼。如果返回的foo被上下文跟蹤,那麼我會期望,當你添加兄弟,上下文將知道他們被添加並將創建一個插入。但是如果沒有被跟蹤,那麼當你添加兄弟姐妹時,上下文不會知道「ADD」。在任何時候你將圖形(foo +它的兄弟姐妹)重新連接到一個上下文中,它們都將會「無變化」,所以你沒有得到想要的插入。

這是所有依賴於GUESS在你的倉庫中正在進行的任何其他操作,以及影響automapper的影響(如果有的話)。我猜測你在上下文知道圖表之前正在做所有的owrk,所以最後,我認爲你正在調用ATTACH,這會導致沒有INSERTS被髮送到數據庫。

+0

感謝您的反饋朱莉。問題實際上是在我的EntityBase對象上。我覆蓋了GetHashCode方法,並在ID本身上返回HashCode ...所以0的Hashcode總是相等的。一旦我評論說,一切都是通過根源共同發射的。我同意100%負面的數字有點駭人聽聞。 – Forest

+0

ahhhhhh ....好抓! :) –