在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;}
}
然而,当我试图在visualstudio2012中首先使用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 server,然后从SQL server中的数据库创建/更新我的.edmx文件。我不确定如何创建EF可以正确识别的一对一关系,并在.edmx文件中创建正确的类
创建1:1关系并不是那么棘手,当然也不是不可能,尽管这不是一个特别常见的要求,在这种情况下,我不明白你为什么想要它?如果人们这么说,那么你说的人不对。
无论如何,使用SQL查询似乎与EF无关,您只是直接使用数据库,在第一个CREATE中,您试图添加约束,但尚未创建另一个表。。。正如你在问题中提到的。
我认为您需要先创建这两个表,然后使用ALTERTABLE添加约束。
此外,在SO中搜索关于1:1的问题会出现很多,所以我建议你这样做。
编辑:所以使用数据库项目(我只有VS Express,所以我没有),你想使用SQL创建"1:1"关系,然后将实体数据模型添加到引用数据库并自动创建1:1关系的(可能不同)项目中?
不幸的是,情况完全不同。当我谈到创建1:1的可能性时,这只是参考EF,而不是数据库本身。正如您所说,在SQL中创建1:1实际上是非常困难/不可能的。我认为,为了插入1:1的关系,您需要以某种方式同时插入两个表,或者在添加行时短暂地禁用约束,这是有道理的。
一般来说,有几个不同的选择。
-
不要不必要地把桌子分开。在真正的1:1中,所有数据都是必需的,所以拆分的唯一原因是出于性能原因(例如分区),在这种情况下我会避免这种情况。
-
将多个表映射到单个实体,如此处所示。
-
创建一个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
);
我建议您也尽可能使用存储生成的身份。
只需从UserDetail表中删除UserDetailID,并使username同时成为User表格的UserID 这是在数据库中建立1:1关系的正确方法,EF可以识别它,并使用数据库优先的方法适当地映射实体。
这个问题是几年前的事了。。并且没有说明ef版本。。但是一个答案是从两个表中移除CCD_ 1。UserID
应该是两个表中唯一的主键。
"unqieidentifier"(GUID)数据类型不应该引起问题(与使用INT相反),但您肯定不想用newId填充它。。