Si vous créez les associations de parents et enfants corrects, vous aurez juste besoin de suivre le modèle de présentation inséré (PM) des relations -entity:
du 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; }
}
Assurez-vous d'utiliser [ Composition] pour forcer WCF RIA à appeler la méthode InsertChild sur le DomainService.
Silverlight:
...
public Child NewChild(Parent parent)
{
return new Child
{
ParentID = parent.ParentID,
Parent = parent,
};
}
...
public void SubmitChanges()
{
DomainContext.SubmitChanges(SaveComplete, null);
}
...
Si le parent n'est pas nouveau, il aura une ParentID. S'il est nouveau, l'ID du parent sera nul. En définissant Child.Parent sur la référence du nouveau parent, RIA comprend ce que vous essayez de faire conserve la référence après qu'elle a été envoyée au serveur.
DomainService sur le serveur:
[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;
}
}
Les deux pièces importantes ici. Premièrement, le '_insertedObjectMap' stocke la relation entre les entités nouvellement insérées qui n'ont pas l'ensemble d'ID. Comme vous le faites dans une transaction et un appel unique à la base de données, l'ID ne sera défini qu'après que toutes les entités ont été insérées. En stockant la relation, le MP enfant peut trouver la version de l'entité du PM Parent en utilisant la base de données. L'entité enfant est ajoutée à la collection Children sur l'entité parent et LINQToSQL ou LINQToEnityFramework doit gérer la clé étrangère pour vous.
La deuxième pièce associe les modifications après l'engagement de la transaction. Dans le scénario où le parent et l'enfant sont tous deux soumis, vous devez vous rappeler de définir la clé étrangère ParentID sur l'enfant.
Mes infos du ChangeSet.Associate() est provenu http://blogs.msdn.com/deepm/archive/2009/11/20/wcf-ria-services-presentation-model-explained.aspx
Ceci est la réponse à ce que je peux dire, donc je vous remercie de l'affichage.Je pense que je suis tombé sur quelque chose de similaire quand je travaillais là-dessus, mais je crois que le problème était qu'en réalité je travaillais avec un graphe d'objet plus compliqué qu'une simple relation parent/enfant, et je ne pense pas que cela Le type de solution évoluera pour faire face à ce genre de complexité. – nlawalker