序:这里我以netcore3.1来做基本底层,net5或者net6或者更高,我觉得举一反三即可!
1.首先第一步:创建项目:
我创建了一个关于数据处理的类库,一个模型类库,一个控制台;
2.引用 相关 包
在数据层 引用 Microsoft.EntityFrameworkCore.SqlServer; Microsoft.EntityFrameworkCore.Tools2个包
在控制台(一般来说是ui层)引用Microsoft.EntityFrameworkCore.Design 包,这样基本就可以了.我是用SQL server数据库做的demo
3.在模型层进行 类的创建,举个例子:
如下:联赛和俱乐部是1对多关系, 俱乐部和球员是1对多关系; 每个字段对应数据库中相应属性,我们在代码里可以 用 相关特性 对 字段进行 设置(如:最大字符数,是否必填,属性类型等等)
/// <summary>
/// 联赛
/// </summary>
public class League
{
public int Id { get; set; } [Required]
[MaxLength(100)]
public string Name { get; set; } [Required,MaxLength(50)]
public string Country { get; set; }
}
/// <summary>
/// 俱乐部
/// </summary>
public class Club
{
//public Club()
//{
// Players = new List<Player>();
//}
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
[Column(TypeName ="date")]
public DateTime DateOfEstablishment { get; set; }//成立的日期
public string History { get; set; }
public League League { get; set; }
public List<Player> Players { get; set; } = new List<Player>();
}
/// <summary>
/// 球员
/// </summary>
public class Player
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; } public List<GamePlayer> GamePlayers { get; set; } = new List<GamePlayer>();
public int ResumeId { get; set; }
public Resume Resume { get; set; }
}
这里没有举例多对多的关系,如果是多对多的关系,那么肯定是有一个中间类作为连接形成 n:1;n:1 ,然后成为n:n
4.在数据层创建 Democontext 类.继承一下DbContext 类; 如下:(我们用DBFirst的方法进行研究)
在这个类中,第一步要写DBSet<上诉类> xxxx {get;set;}
写完关联类后,就该连接数据库了.
连接数据库要重写 OnConfiguring 类,然后optionsBuilder.UseSqlServer("这里是你的SQL server数据库的相关连接")
完了就基础框架就出来了,下边是我自己加的一些东西,如需要可参考
public class DemoContext:DbContext
{
/// <summary>
/// 全局设置 数据变化不被追踪
/// </summary>
//public DemoContext()
//{
// ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
//} #region 第二步: 创建连接字符串
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(ConsoleLoggerFactory)//打印日志在控制台上
.UseSqlServer("Server=127.0.0.1;Database=EFDemoDB;uid=sa;pwd=123456");
}
#endregion #region 定义联合主键
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<GamePlayer>().HasKey(x=>new { x.GameId,x.PlayerId}); //建立 一对一 关系(fluent api)
modelBuilder.Entity<Resume>().HasOne(x => x.Player)
.WithOne(x => x.Resume)
.HasForeignKey<Resume>(x=>x.PlayerId);
}
#endregion #region 第一步: 将类写为DbSet格式的属性
public DbSet<League> Leagues { get; set; }
public DbSet<Club> Clubs { get; set; }
public DbSet<Player> Players { get; set; }
public DbSet<Game> Games { get; set; }
public DbSet<Resume> Resumes { get; set; }
#endregion public static readonly ILoggerFactory ConsoleLoggerFactory =
LoggerFactory.Create(builder=>
{
builder.AddFilter((category,level)=>
category==DbLoggerCategory.Database.Command.Name
&& level ==LogLevel.Information
).AddConsole();//category:种类
});
}
5.数据迁移
打开工具中的 程序包管理控制台,下拉框选中 关于数据的类库
Add-Migration Init //这样就会在数据层生成一个相关文件夹
update-database //这样数据库就可以看到刚才写的类了
6.增,删,查,改
using var context = new DemoContext();//全局都要用到的上下文对象
6.1 增加:
context.Leagues.Add(le1);//增加一条数据
context.Leagues.AddRange(le2,le3);//增加同类型多条数据
context.AddRange(le4,club1);//增加不同类型的多条数据 ;这里会自动识别 属于哪个类别
当然不要忘记 :context.SaveChanges(); 要不然数据库不会执行
6.2 删除: 只能删除被追踪的数据
要做删除,首先要找到要删除哪条数据,然后才能删除
var led1 = context.Leagues.Where(x=>x.Name.Contains("r")).ToList();
context.Leagues.RemoveRange(led1);
context.SaveChanges();
6.3 查询: 查询会涉及到 模糊查询,精确查询,分页查询 ,排序(正序/倒叙)等查询
var lens = context.Leagues.OrderBy(x=>x.Id).Last(x => x.Country == "意大利" || x.Country.Contains("西"));
//var lens = context.Leagues.Where(x=>x.Country=="意大利"||x.Country.Contains("西")).ToList();
这里注意:只有ToList之后,数据库才是真正的执行了. 那么还有哪些方法是调用完才会执行数据库呢?下边我总结了一些,不够请补充
//ToList() First() FirstOrDefault() Single()
//SingleOrDefault() Last() LastOrDefault()
//Count(),LongCount(),Min(),Max(),Average(), Sum() Find():这个方法只能传 [主键Id]
6.4修改: 修改的话一般会遇到 追踪和非追踪的问题
//传统修改:先找出要修改的数据,然后对要修改的进行重新赋值 修改的时候也是只能修改被追踪的数据
//var le5 = context.Leagues.FirstOrDefault();
//le5.Name = "意甲";
//int k = context.SaveChanges(); //一般项目 都是前后端分离的, 前端传递过来的 基本都是json字符串什么的,这时候就不能用追踪了
var le6 = context.Leagues.AsNoTracking().First();//这个AsNoTracking 可以对全局设置:在context类中进行设置 le6.Name = "意大利甲级联赛";
context.Leagues.Update(le6);
var w = context.SaveChanges();
至此,一套基本的efcore的增删查改就完成了,更复杂的需要小伙伴们根据实际情况考虑