C# 使用实体框架的唯一主键

C# 使用实体框架的唯一主键,c#,sql,.net,entity-framework,primary-key,C#,Sql,.net,Entity Framework,Primary Key,我是EF的新手。假设我有一个DB格式的表,如下所示: ID FirstName LastName DateOfBirth ------------------------------------------- 1 John Smith 1.1.1990 2 Mary Wilson 5.1.1991 [Index("IX_UniqueConstraint", 1, IsUnique = true)] p

我是EF的新手。假设我有一个DB格式的表,如下所示:

ID    FirstName     LastName    DateOfBirth
-------------------------------------------
1     John          Smith       1.1.1990
2     Mary          Wilson      5.1.1991
[Index("IX_UniqueConstraint", 1, IsUnique = true)]
public string FirstName { get; set; }

[Index("IX_UniqueConstraint", 2, IsUnique = true)]
public string LastName { get; set; }

[Index("IX_UniqueConstraint", 3, IsUnique = true)]
public DateTime DateOfBirth { get; set; }
[Key]
public string FirstName { get; set; }
现在,我使用EF将新实体插入表中:

dbcontext.Persons.Add(new Person
{
    FirstName = "John",
    LastName = "Smith",
    DateOfBith = "1.1.1990"
});
dbcontext.SaveChanges();
我需要代码来抛出异常,因为数据库中已经存在此行,但EF所做的是将ID列增加1并创建新记录:

ID    FirstName     LastName    DateOfBirth
--------------------------------------------
1     John          Smith       1.1.1990
2     Mary          Wilson      5.1.1991
3     John          Smith       1.1.1990

EF能做到这一点吗?

有了EF,您需要做如下工作:

ID    FirstName     LastName    DateOfBirth
-------------------------------------------
1     John          Smith       1.1.1990
2     Mary          Wilson      5.1.1991
[Index("IX_UniqueConstraint", 1, IsUnique = true)]
public string FirstName { get; set; }

[Index("IX_UniqueConstraint", 2, IsUnique = true)]
public string LastName { get; set; }

[Index("IX_UniqueConstraint", 3, IsUnique = true)]
public DateTime DateOfBirth { get; set; }
[Key]
public string FirstName { get; set; }

这将在3列之间设置一个唯一的约束。

您已经将
ID
列定义为,并且它已被视为主键,并且在表中插入新记录时将增加1。这就是允许您插入重复实体的原因。您需要指定需要声明为PK的列,如果您使用的是代码优先方法,则在您的模型中,或者使用类似以下内容:

ID    FirstName     LastName    DateOfBirth
-------------------------------------------
1     John          Smith       1.1.1990
2     Mary          Wilson      5.1.1991
[Index("IX_UniqueConstraint", 1, IsUnique = true)]
public string FirstName { get; set; }

[Index("IX_UniqueConstraint", 2, IsUnique = true)]
public string LastName { get; set; }

[Index("IX_UniqueConstraint", 3, IsUnique = true)]
public DateTime DateOfBirth { get; set; }
[Key]
public string FirstName { get; set; }
或通过使用唯一约束:

[Index("IX_UniqueConstraint", 1, IsUnique = true)]
public string FirstName { get; set; }

[Index("IX_UniqueConstraint", 2, IsUnique = true)]
public string LastName { get; set; }

[Index("IX_UniqueConstraint", 3, IsUnique = true)]
public DateTime DateOfBirth { get; set; }
您也可以为此目的使用:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Persons>().HasKey(c => new { c.FirstName, c.LastName, c.DateOfBirth });
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasKey(c=>new{c.FirstName,c.LastName,c.DateOfBirth});
}

或者,如果您使用的是DB first方法,您可以在数据库中声明它。

Apply unique constraint能否向我们展示数据库中的表结构(列及其数据类型)(包括您如何定义主键),在我应用C#code下面的一些解决方案之后,C#?@marc#s中的模型类
Person
,看起来像这个公共int ID{get;set;}[Index(“IX#u UniqueConstraint”,1,IsUnique=true)]公共字符串FirstName{get;set;}[Index(“IX#u UniqueConstraint”,2,IsUnique=true)]公共字符串LastName{get;set;}[Index(“IX_UniqueConstraint”,3,IsUnique=true)]public DateTime BirthDate{get;set;}Db-ID为int,LastName为nvarchar,FirstName为nvarchar,BirthDate为DateTime感谢您的快速回复-使用第二个解决方案时我收到此异常:“表'dbo.People'中的列'FirstName'的类型无效,无法用作索引中的键列。”。“我不确定出了什么问题-我的模型类-public int ID{get;set;}[Index(“IX_UniqueConstraint”,1,IsUnique=true)]public string FirstName{get;set;}[Index(“IX_UniqueConstraint”,2,IsUnique=true)]public string LastName{get;set;}[Index(“IX_UniqueConstraint“,3,IsUnique=true)]public DateTime BirthDate{get;set;}@xcelm SQL Server(直到2008 R2)中存在一个限制,即varchar(MAX)和nvarchar(MAX)(以及一些其他类型,如text、ntext)不能在索引中使用。你有两个选择:检查这篇文章是的,它成功了!问题似乎在于varchar的长度(以DB为单位)。我将字符串限制为[StringLength(100)],并将其解决。非常感谢:)虽然它没有像我预期的那样工作-如果我尝试输入First Name=“Joe”和LastName=“Smith”,那么我会得到违反PK错误的信息。我需要的是检查整行(当然只有指定的列)是否已经在DB中,如果其中至少有一行不同,则将记录保存到DB中。知道如何管理吗?@xcelm最后一个使用fluent API的解决方案是什么?你得到同样的还是还没有试过?你好首先谢谢你的快速回复。您的解决方案可以工作,尽管它没有像我预期的那样工作-如果我尝试输入First Name=“Joe”和LastName=“Smith”,那么我将得到违反PK错误的结果。我需要的是检查整行(当然只有指定的列)是否已经在DB中,如果其中至少有一行不同,则将记录保存到DB中。你知道怎么处理吗?