EF4 CTP5 代码优先实现中的实体拆分场景

Posted

技术标签:

【中文标题】EF4 CTP5 代码优先实现中的实体拆分场景【英文标题】:Entity-splitting scenario in EF4 CTP5 code-first implementation 【发布时间】:2011-03-17 17:28:07 【问题描述】:

我认为我正在寻找的实际上是实体分割。但是,我不能 100% 确定我需要的方式是否受支持。因此,我将添加大量细节,希望对您有所帮助。我会将范围限制为一个实体,因为我必须处理的所有实体的答案都是相同的。

所以,我有一个用户实体:

User
ID (int)
CustID (int)
CustomerString (string)
FirstName (string)
LastName (string)
Email (string)

由于我们的数据库是多租户的,每个对象都有与之相关联的所有者的概念。这由所有表中的 CustID 表示。但是,对于将访问此数据服务的客户来说,此 ID 是一个毫无意义的 PK。他们知道他们的 CustomerString,这只是一个唯一的字符串值,等同于我们 Client 表中的 ID。

与User实体相关的两个表如下:

客户

CREATE TABLE [Customers](
 [ID] [int] NOT NULL,
 [Name] [varchar](100) NOT NULL,
 [Description] [varchar](255) NULL,
 [ClientPhone] [varchar](20) NULL,
 [Address] [varchar](255) NULL,
 [CustomerString] [varchar](100) NOT NULL,
 [sys_CreateDate] [datetime] NOT NULL,
 [sys_LastUpdate] [datetime] NOT NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY NONCLUSTERED 
(
 [ID] ASC
)

用户

CREATE TABLE [Users](
 [UserID] [int] IDENTITY(2000000,1) NOT NULL,
 [CustID] [int] NOT NULL,
 [FirstName] [varchar](40) NOT NULL,
 [LastName] [varchar](40) NOT NULL,
 [mail] [varchar](255) NULL,
 [CreateDate] [datetime] NOT NULL,
 [ModifyDate] [datetime] NOT NULL,
 CONSTRAINT [PK2_Users] PRIMARY KEY CLUSTERED 
(
 [UserID] ASC
)

所以,目前,我将 User 实体映射到 Users 表,如下所示:

ID  ==> Users.UserID
CustID ==> Users.CustID
CustomerString <NOT MAPPED>
FirstName ==> Users.FirstName
LastName ==> Users.LastName
Email ==> Users.Mail

现在,我的症结来了。我需要将 CustomerString 映射到 Customers.CustomerString,其中 Users.CustID = Customers.ID。在我看来,根据我的阅读,如果每个表中的 ID 命名相同,这将不是问题。但是,如您所见,情况并非如此。

请帮忙!这是我过去一个月左右一直在工作的这个项目的绝对要求。

提前感谢您提供的任何帮助!

瑞恩

【问题讨论】:

User.CustomerString 可以是只读字符串吗? 【参考方案1】:

我认为这是不可能的。第一个问题是 EF 不能使用唯一键(可能是available in next major version)。因此,您不能在 Customer->Id 和 User->CustId 之间强制执行 1:1 关系(这需要唯一键约束)。要在 EF 中启用 1:1 关系,实体必须“共享”PK。这意味着您只能在您显然不想要的 Customer->Id 和 User->Id 上创建 1:1 关系。

第二个问题是生成的 User 类不是实体。它不包含两个类的所有列。它是这两个实体的投影。您可以使用这两个实体并创建自定义 linq 查询来投影到这个只读类,例如:

var query = from u in context.Users
            join c in context.Customers on u.CustId equals c.Id
            select new UserProjection
              
                Id = u.Id,
                CustId = c.Id,
                CustomerString = c.CustomerString,
                FirstName = u.FistName,
                LastName = u.LastName
                Email = u.Mail
              ; 

另外请注意,CTP5 已经过时。 EF 4.1 RC 是 relased two days ago。

【讨论】:

我实际上注意到 4.1 发布后发布。 我不完全理解您关于这不是一个实体的评论,因为用户不包含两个表中的所有字段。这真的是 EF 中实体的要求吗?它似乎立即破坏了建模数据以匹配您的业务实体的目的。 db 表实际上多久部分或全部反映您的业务实体?它们通常由从不同表中提取的数据组成,但通常不是全部。 (想想在查找表上创建/修改日期或 pks。) @Rocky:问题是您的用户类不包含映射表中的所有不可为空的列。因此,您的应用程序将永远无法插入用户。 啊,我明白你在说什么。我仍然很好奇这是否是一项要求,尽管这纯粹是一项只读服务,并且永远不会针对此模型执行更新/插入/删除?感谢您的反馈!

以上是关于EF4 CTP5 代码优先实现中的实体拆分场景的主要内容,如果未能解决你的问题,请参考以下文章

WCF 数据服务和 EF4 CTP5,如何为查询配置默认的急切加载模式?

EF4 CTP5 Code First 方法忽略表属性

实体框架 CTP5,代码优先。可选的导航属性

实体框架代码优先 CTP5:如何定义非原始类型

实体框架 CTP5,代码优先。多对多级联删除

EF4 Code only ctp5:如何设置连接字符串 devart oracle?