【问题标题】:RIA Services: Inserting multiple presentation-model objectsRIA 服务:插入多个表示模型对象
【发布时间】:2011-01-11 02:14:54
【问题描述】:

我正在使用基于 LINQ to SQL 类的表示模型通过 RIA 服务共享数据。在 Silverlight 客户端上,我创建了几个新实体(专辑和艺术家),将它们相互关联(通过将专辑添加到艺术家的专辑收藏,或在专辑上设置 Artist 属性 - 任一工作),添加将它们添加到上下文中,并提交更改。

在服务器上,我收到两个单独的插入调用 - 一个用于专辑,另一个用于艺术家。这些实体是新的,因此它们的 ID 值都设置为默认的 int 值(0 - 请记住,根据我的数据库,这可能是数据库中的有效 ID),因为据我所知,您没有设置 ID对于客户端上的新实体。如果我通过我的 RIA 服务将 LINQ 传输到 SQL 类,这一切都可以正常工作,因为即使专辑插入包含艺术家并且艺术家插入包括专辑,两者都是实体并且 L2S 上下文可以识别它们。但是,对于我的自定义表示模型对象,我需要将它们转换回 LINQ to SQL 类维护过程中的关联,以便将它们添加到 L2S 上下文中。

简而言之,据我所知,这是不可能的。每个实体都有自己的 Insert 调用,但您不能只插入一个实体,因为没有 ID,关联就会丢失。如果数据库使用 GUID 标识符,那就另当别论了,因为我可以在客户端上设置这些标识符。

这可能吗,还是我应该追求另一种设计?

【问题讨论】:

    标签: wcf-ria-services presentation-model


    【解决方案1】:

    如果您创建了正确的父子关联,您只需跟踪插入的演示模型 (PM)-实体关系:

    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 调用 DomainService 上的 InsertChild 方法。

    银光:

    ...
    public Child NewChild(Parent parent)
    {
        return new Child
                    {
                        ParentID = parent.ParentID,
                        Parent = parent,
                    };
    }
    ...
    public void SubmitChanges()
    {
        DomainContext.SubmitChanges(SaveComplete, null);
    }
    ...
    

    如果 Parent 不是新的,它将有一个 ParentID。如果它是新的,则父 ID 将为空。通过将 Child.Parent 设置为新 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”存储新插入的没有设置 ID 的实体之间的关系。由于您是在事务和对数据库的单次调用中执行此操作,因此只有在插入所有实体后才会设置 ID。通过存储关系,Child PM可以使用数据库找到Parent PM的实体版本。 Child 实体被添加到 Parent 实体上的 Children 集合中,并且 LINQToSQL 或 LINQToEnityFramework 应该为您处理外键。

    第二部分是在事务提交后关联更改。在Parent和Child都提交的情况下,一定要记得在Child上设置ParentID外键。

    我的 ChangeSet.Associate() 信息来自:http://blogs.msdn.com/deepm/archive/2009/11/20/wcf-ria-services-presentation-model-explained.aspx

    【讨论】:

    • 据我所知,这就是答案,感谢您的发帖。我想我在处理这个问题时偶然发现了类似的东西,但我认为问题在于,实际上我正在处理一个比单父/子关系更复杂的对象图,而且我不认为这这种解决方案可以扩展以应对这种复杂性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多