EF 数据注释和 Code Fluent





5.00/5 (13投票s)
展示如何使用数据注解和 Code Fluent 配置 Entity Framework Code First。
引言
在第一篇文章 EF Code First: 让我们试试 中,我们看到了如何使用 EF Code First 生成表。在第二篇文章中,我解释了如何为 Code First 声明外键:EF Code First:添加外键关系。在本文中,我们将了解如何使用数据注解和 Code Fluent 来调整我们的数据库。
使用代码
现在我们已经学会了如何 使用 Code First 创建数据库 以及如何 声明外键关系,让我们看看还有什么可以配置的。在 Code First 中,有两种配置数据库创建的方法。第一种是使用数据注解,就像我们在关于外键关系的第二篇文章中看到的那样,第二种是使用 Fluent API。 让我们看看它是如何工作的。
使用 DataAnnotation 定义列的 MaxLength
首先,我们将定义我们的列。如果我们看一下表 Project,我们可以看到我们类中从字符串类型创建的所有列都是 nvarchar(max)
。
这并不是真的有用,我们不希望项目名称这么长。因此,我们将为我们的项目名称定义一个最大长度,并且我们还将指示一个项目应该有一个名称。以下是如何使用 DataAnnotations 来实现它
public class Project
{
public int ProjectId { get; set; }
[MaxLength(255)]
[Required]
public string Name { get; set; }
public int ManagerId { get; set; }
[ForeignKey("ManagerId")]
public Person Manager { get; set; }
}
运行应用程序并检查您的数据库列
这次,Name 列定义了最大长度,并且 Name 列设置为 Not null。
使用 DataAnnotation 定义列的名称
这次,我们将看到如何定义列的名称。看一下你的 Person
类
public class Person
{
public int PersonId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime BirthDate { get; set; }
}
假设我们不希望属性 BirthDate
存储在名为 BirthDate 的列中,而是存储在名为 Birth 的列中。
以下是我们如何修改我们的类
using System.ComponentModel.DataAnnotations;
public class Person
{
public int PersonId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
[Column("Birth")]
public DateTime BirthDate { get; set; }
}
运行应用程序并检查您的数据库
你可以看到列名已更改。
使用 DataAnnotation 将属性声明为外键
首先,我们将添加一个新类 Task
,其中包含指向 Project
和 Person
类的外键,在 Project
类中添加一个任务列表,并删除 Manager
属性。
public class Task
{
public int TaskId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int PersonId { get; set; }
[ForeignKey("PersonId")]
public Person AssignedTo { get; set; }
public int ProjectId { get; set; }
[ForeignKey("ProjectId")]
public Project Project { get; set; }
}
public class Project
{
public int ProjectId { get; set; }
MaxLength(255)]
[Required]
public string Name { get; set; }
public List<Task> Tasks { get; set; }
}
我们使用 DataAnnotation 来指定指向 Project 和 Person 表的外键。然后我们修改我们的 Context 类
public class MyContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<Task> Tasks { get; set; }
public MyContext()
{}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
我们运行控制台应用程序。 这是结果
好的,到目前为止一切正常。让我们重新添加 Project
类中的 Manager
属性
public class Project
{
public int ProjectId { get; set; }
[MaxLength(255)]
[Required]
public string Name { get; set; }
public int ManagerId { get; set; }
[ForeignKey("ManagerId")]
public Person Manager { get; set; }
public List<Task> Tasks { get; set; }
}
在这里我们得到一个 SqlException
Introducing FOREIGN KEY constraint 'FK_Tasks_Projects_ProjectId'
on table 'Tasks' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify
other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
此错误并非来自 Entity Framework 或 Code First,而是来自 SQL Server。 它不想创建表和约束,因为它估计如果我们保持原样会出现一些问题。 它要求我们在删除时指定一个动作(以避免多次级联删除)或修改我们的约束。
因为我们不想修改我们的约束,我们将在删除时指定一个动作。这是我们无法使用 DataAnnotations 完成的第一个操作。我们将不得不使用 Code Fluent 来完成它。
使用 Code Fluent 将属性声明为外键
现在我们已经了解了如何使用 DataAnnotation 配置数据库的生成,我们将了解如何使用 Fluent API 来完成相同的事情,甚至更多。
此配置应在 Context 类中完成。这是我如何修改它以声明 Task 和 Project 之间的外键
public class MyContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<Task> Tasks { get; set; }
public MyContext()
{}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Task>().HasRequired(t => t.Project).WithMany(
p => p.Tasks).HasForeignKey(t => t.ProjectId).WillCascadeOnDelete(false);
modelBuilder.Entity<Task>().HasRequired(p => p.AssignedTo);
}
}
这很容易理解。一个任务应该链接到一个可以有多个任务的项目,这种关系将使用属性 ProjectId
完成,并且在删除的情况下不会有任何操作。我们对 Task
和 Person
之间的关系做了同样的事情。现在我们需要像这样修改我们的 Task
类,以删除 DataAnnotations
public class Task
{
public int TaskId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int PersonId { get; set; }
public Person AssignedTo { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
我们可以删除指令
using System.ComponentModel.DataAnnotations;
这次,当我们运行应用程序时,没有错误,并且我们的表已正确创建
使用 Code Fluent 定义列名
现在我们将修改我们的 Person
类以使用 Code Fluent。首先,我们删除 Attribute 列。
public class Person
{
public int PersonId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime BirthDate { get; set; }
}
然后我们转到 Context 类并添加下面的行
modelBuilder.Entity<Person>().Property(d => d.BirthDate).HasColumnName("Birth");
将列定义为不可为空
我们还将指示一个项目应该有一个经理
modelBuilder.Entity<Project>().HasRequired(p => p.Manager);
定义属性的最大长度,并且它是一个必需的信息
modelBuilder.Entity<Project>().Property(p => p.Name).HasMaxLength(255).IsRequired();
modelBuilder.Entity<Project>().HasRequired(p => p.Manager);
本文现在已经完成。我希望它能帮助您了解 DataAnnotations 和 Code Fluent 的工作原理。在以后的文章中,我们将了解如何组织我们的配置。在下一篇文章中,我们将讨论 Data Annotations 和 Code Fluent。
历史
- 2012 年 4 月:第一篇文章。