实体框架 - 使用共享主键添加实体(及其导航属性)

时间:2012-03-15 12:19:55

标签: entity-framework navigation-properties shared-primary-key

这是我要解决的问题的简化版本:

有两个实体:

项目

ItemID(PK)

其他简单的属性......

WorkItem(导航属性)

工作项目

ItemID(PK)

其他简单属性......

项目(导航属性)

我需要为它创建一个Item,一个WorkItem,我需要设置两个导航属性,以便两个实体在保存之前可以互相指向。

我可以这样做:

  Item newItem = Item.CreateItem(0, blah,blah,blah);
  service.AddToItems(newItem);


  WorkItem newWorkItem = new WorkItem();           
  service.AddToWorkItems(newWorkItem);

  //set the navigation properties
  newItem.WorkItem = newWorkItem;
  newWorkItem.Item = newItem;

不幸的是,当涉及到保存时,这会失败。我相信EF在尝试设置WorkItem的Item关联时会尝试设置WorkItem的主键。

有人可以告诉我正确的方法吗?


更新:

所以,我尝试使用继承来构建模型。该模型建立并验证。

不幸的是,为我的模型添加WCF数据服务并尝试在浏览器中查看服务给了我:

  ..... <m:message xml:lang="en-US">An error occurred while processing this request.    </m:message>
<m:innererror>
  <m:message>Navigation Properties are not supported on derived entity types. Entity Set 'app_Items' has a instance of type 'tempmodel.app_CostItem', which is an derived entity type and has navigation properties. Please remove all the navigation properties from type 'tempmodel.app_CostItem'.</m:message>
  <m:type>System.InvalidOperationException</m:type>
  <m:stacktrace>   at System.Data.Services.Serializers.SyndicationSerializer.WriteObjectProperties(IExpandedResult expanded, ......

CostItem是另一个实体,如WorkItem,它派生自Item。

2 个答案:

答案 0 :(得分:0)

根据您提供的示例,我相信您应该使用继承。 WorkItem实体应该从Item实体继承。然后,在您的代码中,您只需要使用WorkItem实体,它也将具有Item实体的所有属性。另外,WorkItem实体将使用Item实体中的键。

答案 1 :(得分:0)

我在每个客户端部分“子”类中创建了一个虚拟属性:

    private Item _BaseItem;
    [AtomIgnore]
    internal Item BaseItem
        {
        get
            {
            if (_BaseItem != null)
                return _BaseItem;
            else
                return this.Item;                
            }
        set
            {
            _BaseItem = value;
            OnPropertyChanged("Item");
            }
        }

客户端上的代码使用此BaseItem属性反向遍历对象图。所以建立关系的代码现在看起来像这样:

 Item newItem = Item.CreateItem(0, blah,blah,blah);
 service.AddToItems(newItem);


 WorkItem newWorkItem = new WorkItem();           
 service.AddToWorkItems(newWorkItem);

 //set the navigation properties
 newItem.WorkItem = newWorkItem;
 newWorkItem.**BaseItem** = newItem;

注意,BaseItem属性被声明为internal;这是因为序列化程序不会尝试序列化属性并将其发送到服务器。

[AtomIgnore]是我创建的属性,在我的DataServiceContext.WritingEntity处理程序中查找。处理程序在将属性标记为发送到服务器之前将其删除。如果属性是ref类型,这种技术似乎不起作用,因此使用内部。

将其声明为内部也意味着它无法从XAML绑定,幸运的是我只需要绑定到几个属性,这样就可以直接解决问题。