4

EF Code First中,我们可以通过这样的编码来创建一对一的关系:

public class User
{
public int UserID {get;set;}
public string Name {get;set;}
public int UserDetailID {get;set;}

public UserDetail Detail {get;set;}
}

public class UserDetail
{
public int UserDetailID {get;set;}
public string Address {get;set:}
public int UserID {get;set;}

public User User {get;set;}

}

但是,当我尝试在 Visual Studio 2012 中首先使用 EF 数据库创建相同的关系时,我遇到了麻烦。这是我的代码:

CREATE TABLE [dbo].[Users] (
[UserID]                 UNIQUEIDENTIFIER CONSTRAINT [DF_Users_UserID] DEFAULT (newid()) NOT NULL,
[UserDetailID]                 UNIQUEIDENTIFIER NOT NULL,
[Name]                      NVARCHAR (50)    NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([UserID] ASC),
CONSTRAINT [FK_Users_UserDetails] FOREIGN KEY ([UserDetailID]) REFERENCES [UserDetails]([UserDetailID])
);

CREATE TABLE [dbo].UserDetails] (
[UserDetailID]     UNIQUEIDENTIFIER CONSTRAINT [DF_UserDetails_UserDetailID] DEFAULT (newid()) NOT NULL,
[UserID]           UNIQUEIDENTIFIER NOT NULL,
[Address]             NVARCHAR(100) NOT NULL,
CONSTRAINT [PK_UserDetails] PRIMARY KEY CLUSTERED ([UserDetailID] ASC),
CONSTRAINT [FK_UserDetails_Users] FOREIGN KEY ([UserID]) REFERENCES [dbo].[Users] ([UserID])

错误消息类似于

"Error  2   SQL01767: Foreign key 'FK_Users_UserDetails' references invalid table 'UserDetails'.    

我认为这个错误的原因可能是当它试图引用外键“UserDetailID”时,它发现它还没有被创建。但是我不知道如何解决这个问题,我什至不知道这是解决问题的方法,我知道与 EF 建立一对一的关系很棘手,或者有些人甚至说这是不可能的。谁能给我任何建议?谢谢你。

更新:为了澄清我的情况,我正在尝试在 Visual Studio 2012 数据库项目中设计数据库,然后将其发布到 SQL 服务器,然后从 SQL 服务器中的数据库创建/更新我的 .edmx 文件。我不确定如何创建 EF 可以正确识别的一对一关系并在 .edmx 文件中创建正确的类。

4

3 回答 3

7

创建 1:1 关系并不是那么棘手,当然也不是不可能,尽管这不是一个特别常见的要求,在这种情况下,我不明白你为什么想要它?如果人们这样说,那么你是在和错误的人交谈。

无论如何,使用 SQL 查询似乎与 EF 无关,您只是直接使用数据库,在第一个 CREATE 中,您尝试添加约束但尚未创建另一个表...你在你的问题中提到。

我认为您需要先创建两个表,然后使用 ALTER TABLE 添加约束。

此外,在 SO 中搜索有关 1:1 的问题也很多,所以我建议你这样做。

编辑:所以使用数据库项目(我只有 VS Express,所以我没有那些)你想使用 SQL 创建一个“1:1”关系,然后将实体数据模型添加到引用的(可能不同的)项目中数据库和自动建立1:1的关系?

不幸的是,这是一个完全不同的故事。当我谈论创建仅参考 EF 而不是数据库本身的 1:1 的可能性时。正如您所说,在 SQL 中创建 1:1 实际上非常困难/不可能。我认为这是有道理的,为了插入 1:1 关系,您需要以某种方式同时插入两个表,或者在添加行时短暂地摆弄禁用约束。

一般来说,有几种不同的选择。

  1. 不要不必要地拆分表格。在真正的 1:1 中,所有数据都是必需的,因此拆分的唯一原因是出于性能原因(例如分区),在这种情况下我会避免这样做。

  2. 将多个表映射到单个实体,如此处所示

  3. 创建 1:0..1 关系并在应用程序中强制执行您自己的要求。

在选项 2 或 3 中,您可以使用以下 SQL 创建关系,该关系在第二个表上使用与关系中的 FK 相同的 PK。

CREATE TABLE [dbo].[Users] (
[UserID] UNIQUEIDENTIFIER CONSTRAINT [DF_Users_UserID] DEFAULT (newid()) NOT NULL,
[Name] NVARCHAR (50)    NOT NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([UserID] ASC),
);

CREATE TABLE [dbo].[UserDetails] (
[UserID]           UNIQUEIDENTIFIER NOT NULL,
[Address]             NVARCHAR(100) NOT NULL,
CONSTRAINT [PK_UserDetails] PRIMARY KEY CLUSTERED ([UserID] ASC),
CONSTRAINT [FK_UserDetails_Users] FOREIGN KEY ([UserID]) REFERENCES [dbo].[Users] ([UserID]) ON DELETE CASCADE 
);

我建议您也尽可能使用商店生成的身份。

于 2013-06-23T08:37:45.303 回答
2

只需从UserDetail表中删除UserDetailID并将UserID设为User表的UserID列的主键和外键。

这是在数据库中建立 1:1 关系的正确方法,EF 识别它并使用数据库优先方法适当地映射实体。

于 2016-06-06T11:19:17.710 回答
1

这个问题是几年前的.. ef 版本没有说明.. 但一个答案是UserDetailID从两个表中删除。UserID应该是两个表上唯一的主键。

'unqieidentifier' (GUID) 数据类型不应该造成问题(反对使用 INT),但您当然不想用 newId 填充它。

于 2015-06-16T16:11:20.290 回答