Если вы создаете правильный родитель-ребенок ассоциацию, вам просто нужно отслеживать модель вставлено представление (PM) -логический объект отношения:
РМА:
public class Parent
{
[Key]
public int? ParentID { get; set; }
[Include]
[Composition]
[Association("Parent_1-*_Child", "ParentID", "ParentID", IsForeignKey = false)]
public IEnumerable<Child> Children { get; set; }
}
public class Child
{
[Key]
public int? ChildID { get; set; }
[Include]
[Association("Parent_1-*_Child", "ParentID", "ParentID", IsForeignKey = true)]
public Parent Parent { get; set; }
}
Обязательно используйте [ Composition], чтобы заставить WCF RIA вызвать метод InsertChild в DomainService.
Silverlight:
...
public Child NewChild(Parent parent)
{
return new Child
{
ParentID = parent.ParentID,
Parent = parent,
};
}
...
public void SubmitChanges()
{
DomainContext.SubmitChanges(SaveComplete, null);
}
...
Если Родитель не является новым, он будет иметь ParentID. Если он новый, идентификатор родителя будет нулевым. Установив Child.Parent на ссылку нового родителя, RIA понимает, что вы пытаетесь сохранить, сохраняет ссылку после ее отправки на сервер.
DomainService на сервере:
[EnableClientAccess]
public class FamilyDomainService : DomainService
{
private readonly IDictionary<object, EntityObject> _insertedObjectMap;
public void InsertParent(Parent parent)
{
ParentEntity parentEntity = new ParentEntity();
ObjectContext.AddToParents(parentEntity);
_insertedObjectMap[parent] = parentEntity;
ChangeSet.Associate(parent, parentEntity, (p, e) => p.ParentID = e.ParentID;
}
public void InsertChild(Child child)
{
var childEntity = new ChildEntity();
if (child.ParentID.HasValue) // Used when the Parent already exists, but the Child is new
{
childEntity.ParentID = child.ParentID.GetValueOrDefault();
ObjectContext.AddToChildren(childEntity);
}
else // Used when the Parent and Child are inserted on the same request
{
ParentEntity parentEntity;
if (child.Parent != null && _insertedObjectMap.TryGetValue(child.Parent, out parentEntity))
{
parentEntity.Children.Add(childEntity);
ChangeSet.Associate(child, childEntity, (c, e) => c.ParentID = e.Parent.ParentID);
}
else
{
throw new Exception("Unable to insert Child: ParentID is null and the parent Parent cannot be found");
}
}
_insertedObjectMap[child] = childEntity;
ChangeSet.Associate(child, childEntity, (c, e) => c.ChildID = e.ChildID);
}
protected override bool PersistChangeSet()
{
ObjectContext.SaveChanges();
_insertedObjectMap.Clear();
return true;
}
}
Два важных частей здесь. Во-первых, '_insertedObjectMap' сохраняет взаимосвязь между вновь вставленными объектами, у которых нет набора идентификаторов. Поскольку вы делаете это в транзакции и одном вызове в БД, идентификатор будет установлен только после того, как все объекты были вставлены. Сохраняя связь, PM ребенка может найти версию сущности родительского PM с использованием базы данных. Объект Child добавляется в коллекцию Children на родительском объекте, а LINQToSQL или LINQToEnityFramework должны обрабатывать внешний ключ для вас.
Вторая часть связывает изменения после совершения транзакции. В сценарии, в котором представлены оба родителя и ребенка, вы должны помнить о том, что для дочернего элемента ParentID задан внешний ключ.
Моя информация от ChangeSet.Associate() приходилась: http://blogs.msdn.com/deepm/archive/2009/11/20/wcf-ria-services-presentation-model-explained.aspx
Это ответ на вопрос, насколько я могу сказать, так что спасибо за сообщение.Я думаю, что наткнулся на что-то подобное, когда я работал над этим, но я считаю, что проблема в том, что на самом деле я работал с более сложным графиком объектов, чем просто с одним родительским/дочерним отношением, и я не думаю, что это решение такого масштаба будет масштабироваться, чтобы справиться с такой сложностью. – nlawalker