1. 安装 EF Core 依赖包
对于 SQL Server 数据库,只需安装 Microsoft.EntityFrameworkCore.SqlServer
包即可。
2. 配置数据库连接字符串
public class MyDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Dog> Dogs { get; set; }
public DbSet<Cat> Cats { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
// 如果没有 `Demo1` 数据库,EF Core 会尝试创建一个。
// 如果遇到连接 SQL Server 时证书不受信任的问题,请加上 `TrustServerCertificate=True`.
string connectionString = "Server=.;Database=Demo1;uid=sa;pwd=sasa;TrustServerCertificate=True;";
optionsBuilder.UseSqlServer(connectionString);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 通过加载当前类,动态获取当前类所在的程序集的所有配置文件
var assembly = this.GetType().Assembly;
modelBuilder.ApplyConfigurationsFromAssembly(assembly);
}
}
3. 配置实体类和实体配置文件
// 实体类
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public DateTime PubDate { get; set; }
public double Price { get; set; }
}
// 实体配置文件
public class BookConfig : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books"); // 自定义表名称
builder.Property(x => x.BookId).UseSequence("BookSequence"); // 使用序列
builder.Property(x => x.Title).HasMaxLength(256).IsRequired(); // Title 字段最大长度256 且不能为空
builder.Property(x => x.Price).HasColumnName("T_Price").HasColumnType("decimal(10,2)").IsRequired(); // 自定义Price的字段名称 和数据库类型且不能为空
}
}
4. 使用数据库迁移脚本保存表结构到数据库
为了使用迁移功能,还需要安装 Microsoft.EntityFrameworkCore.Tools 包。
在 Visual Studio 的程序包管理器控制台中运行以下命令:
Add-Migration AddBooks
Update-Database
约定大于配置示例
/// 没有编写DogConfig类,那生成的表名就为DbSet 中的Dogs
/// 主键为DogId
public class Dog
{
public Guid DogId { get; set; }
public int KeyId { get; set; }
public string Name { get; set; }
}
使用 Data Annotations 示例
[Table("T_Cat")] // 对应的表名
public class Cat
{
public int CatNum { get; set; }
[Column("CatId")] // 自定义列名
public Guid CatId { get; set; }
[MaxLength(200)]
[Required]
[Column("Cat_Name")]
public string CatName { get; set; }
}
查询视图示例
public class BookPersonsInfo
{
public string Title { get; set; }
public DateTime PubDate { get; set; }
public string Name { get; set; }
public int BookId { get; set; }
public int PersonId { get; set; }
}
// 基于数据库已有的视图来映射实体
public class BookPersonsInfoConfig : IEntityTypeConfiguration<BookPersonsInfo>
{
public void Configure(EntityTypeBuilder<BookPersonsInfo> builder)
{
builder.ToView("BookPersonsInfo");
builder.Property(x => x.BookId);
builder.HasKey(x => x.BookId);
builder.Ignore(x => x.PubDate);
}
}
static void Test2()
{
using (var myDb = new MyDbContext())
{
var data = myDb.BookPersonsInfo.Where(p => p.BookId > 0);
foreach (var item in data)
{
Console.WriteLine($"Item Name: {item.Name}; PubDate: {item.PubDate.ToString("yyyy-MM-dd HH:mm:ss")}");
}
}
}
深入研究 Migrations
使用迁移脚本可以对当前连接的数据库执行编号更高的迁移(向上迁移),也可以执行回退到旧的迁移(向下迁移)。
除非有特殊需求,否则不要删除 Migrations 文件夹下的代码。
_EFMigrationHistory 表用于记录迁移记录。
其他 Migrations 命令
1、Update-Database xxx 将数据库回滚到xxx指定版本,迁移脚本不变。
2、Remove-Migration 删除最后一次迁移的脚本。
3、Script-Migration 生成迁移 SQL 代码,可以将开发环境添加的字段生成 SQL 脚本放到生产环境执行。
4、Script-Migration from to生成从一个版本到另一个版本的 SQL 脚本;
5、生成从指定版本到最新版本的 SQL 脚本:Script-Migration xxx。
多表关联查询示例
static void Test1()
{
using (MyDbContext ctxDb = new MyDbContext())
{
var person = new Person
{
BirthDay = new DateTime(1997, 09, 19, 16, 20, 30),
KeyId = Guid.NewGuid(),
Age = 26,
Description = "Person 1",
Name = "Yang XX"
};
ctxDb.Persons.Add(person);
ctxDb.SaveChanges();
var persons = ctxDb.Persons.First(p => p.Name == "Yang XX");
var book = new Book
{
Title = "Sue",
PubDate = DateTime.Now,
Price = 89,
PersonId = persons.PersonId
};
ctxDb.Books.Add(book);
ctxDb.SaveChanges();
var booksPerson = from t1 in ctxDb.Books
join t2 in ctxDb.Persons on t1.PersonId equals t2.PersonId
select new
{
t1.Title,
t1.PubDate,
t1.Price,
t2.BirthDay,
t2.Name
};
var sql = booksPerson.ToQueryString(); // 获取查询的 SQL 日志
Console.WriteLine(sql);
}
}
public class Person
{
public Guid KeyId { get; set; }
public string Name { get; set; }
public DateTime BirthDay { get; set; }
public int Age { get; set; }
public string Description { get; set; }
public int PersonId { get; set; }
}
public class PersonConfig : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
builder.ToTable("T_Persons");
builder.Property(x => x.BrithDay).HasPrecision(0);
builder.Property(x => x.Name).HasMaxLength(50).IsRequired();
builder.HasIndex(x => x.KeyId).IsUnique();
//builder.HasIndex(x => new { x.Name, x.Description });
//builder.HasIndex(x => x.PersonId).IsClustered();
}
}