4

我有一个客户端/服务器应用程序,其中服务器使用实体框架作为 ORM。每个要发送到客户端的实体都由 DTO 类表示。

实体框架和 DTO 类之间的映射是使用 AutoMapper 处理的。

假设我们有以下表格:

Person (string Name, int CountryID) Country (int CountryID, int Population, string Name)

它们由以下 EF 类表示:

class Person
{
 public string Name { get; set; }
 public int CountryID { get; set; }
 public Country Country { get; set;}
}

class Country
{
 public int CountryID { get; set; }
 public int Population { get; set; }
 public string Name { get; set;}
}

依次由以下 DTO 表示:

class PersonDTO
{
 public string Name { get; set; }
 public CountryDTO Country { get; set;}
}

class CountryDTO
{
 public int CountryID { get; set; }
 public int Population { get; set; }
 public string Name { get; set;}
}

数据库的初始状态表示一个空的 Person-Table 和一个 Country-table,它有一个条目:(1, 123, 'CountryXYZ')

客户的应用程序任务是创建一个新的人员实体并将其国家参考附加到可用的“国家XYZ”国家实体。

为此,客户端应用程序首先请求可用的 CountryDTO。然后它创建一个新的 PersonDTO 实例并将其 Country 属性设置为它从服务器接收到的唯一 CountryDTO。然后这个 PersonDTO 实例被发送回服务器。服务器依次将 PersonDTO-instance 映射回 Person-instance。

服务器的最后一步现在是将 Person-instance 存储在 ObjectContext 中并调用 ObjectContext.SaveChanges()。

这种方法的问题是,只要我调用 ObjectContext.SaveChanges(),就会在数据库中创建一个新的 Country-row,而不仅仅是使用可用的 Country-row。我在这里想念什么?

我是 EF 的新手,我认为这个用例很常见......所以我希望有一个简单的解决方法。

如果问题描述不够清楚,请告诉我。

谢谢!

4

2 回答 2

2

如果您知道客户端将始终使用它已​​经从您的服务器收到的国家/地区(它是现有的),您可以简单地修改您的保存逻辑以使用:

objectContext.PersonSet.AddObject(personToSave);
objectContext.ObjectStateManager
             .ChangeObjectState(personToSave.Country, EntityState.Unchanged);
objectContext.SaveChanges();

如果您使用AddObject方法,则实体及其所有关系都被标记为已添加,并将作为新对象插入到数据库中,除非您重新配置它们的状态。

您的实体还公开了 FK 属性,因此您可以在将 DTO 映射回实体而不是创建国家/地区实例时使用 FK 属性。在这种情况下,您将不需要处理更改关系状态,因为该关系将仅通过整数列表示。

如果客户端可以在单个调用中创建两者PersonCountry您将需要在 DTO 中使用一些标志来区分现有实体或新实体,或者您必须查询数据库以验证是否Country已经存在。

于 2012-04-07T16:54:45.787 回答
1

这是一个使用自我跟踪实体可能对您有用的实例。

它使用 T4 模板来生成您的实体类,并且可以使用 WCF 来回传输它们。但是,您需要在客户端和服务器上共享包含实体的程序集。

如果您同时控制两者,并且两者都使用.Net,我会走那条路。

于 2012-04-06T23:59:24.443 回答