【发布时间】:2011-10-09 14:00:36
【问题描述】:
我有一个关于在 Entity Framework 4.1 CF 中将子级添加到根实体的问题。
考虑以下基础设施Entity基类和两个POCO:
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:many 关系的数据库。
我对这两个实体的唯一流畅映射是:
modelBuilder.Entity<Foo>()
.HasMany(x => x.Siblings)
.WithRequired(x=>x.Foo)
.WillCascadeOnDelete(true);
没有Foo 就没有FooSibling。吹走Foo,你吹走它所有的兄弟姐妹。这件作品有效。
问题是在将 FooSiblings POCO 添加到 Foo 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, .... });
我的 CookieCutter 存储库正在抽象所有 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 请求的生命周期内保持不变。
如果不可能,您会给出什么建议?
【问题讨论】:
标签: .net entity-framework-4 domain-driven-design ef-code-first poco