У меня есть вопрос относительно добавления дочерних элементов в корневую сущность в Entity Framework 4.1 CF.
Учитывая следующую инфраструктуру базового класса сущности и два 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: многие.
Единственное свободное отображение, которое я имею на этих двух объектах:
modelBuilder.Entity<Foo>()
.HasMany(x => x.Siblings)
.WithRequired(x=>x.Foo)
.WillCascadeOnDelete(true);
Нет FooSibling
безFoo
.Сдуйте 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" });
Только один сохраняется в базе данных.
Единственный известный мне способ сделать это без использования отрицательных чисел - это использовать DooSet FooSiblings непосредственно в методе обслуживания:
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-запроса.
Если это невозможно, какие предложения вы бы дали?