EF Core 二 、 入门 EF Core (简单操作)

我们将开始真正的EF之旅了,这里使用SqlServer数据,然后DbFirst
为嘛使用SqlServer,目前公司的整体业务全部在SqlSever,所以很多产品业务都是依托于这个,当然也在考虑做数据库切换,切换EF Core就是开始,为后续做好准备,目前SqlServer的linux集群部署太麻烦了,至少我是这样认为的,而且很多客户也都人格上排斥 … 说多了都是泪 …
然后就是DbFirst,公司是业务型公司,注重业务需求的设计,所以在需求开发之前,表结构的设计基本上都已经确定,基于现在的业务以及背景,可能DbFirst更加适合,当然Code First也不会丢掉的

一、安装 EF Core

新建类库,用来引用 Microsoft.EntityFrameworkCore.SqlServer
在这里插入图片描述
如果在项目中有类似的第三方程序集引用,建议放入统一的程序集,这样不用到处维护引用信息;而且有利于后期解耦,其他业务相关的都依赖统一接口就可以,这样具体的实现引用只是一个插件而已;

二、生成数据表结构

为了做测试,这里生成两张表,TestTable,以及TestTableDetail,用来模拟主从表的场景;一步步来啊

CREATE TABLE [dbo].[TestTable](
        [Id] [INT] NOT NULL,
        [Name] [NVARCHAR](200) NOT NULL,
        PRIMARY KEY CLUSTERED 
        (
                [Id] ASC
        )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
        ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[TestTableDetail](
        [Id] [INT] NOT NULL,
        [PID] [INT] NOT NULL,
        [Name] [NVARCHAR](200) NOT NULL,
PRIMARY KEY CLUSTERED 
(
        [Id] ASC
        )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

三、建立实体对象

建立实体对象,用来与数据库的对象进行匹配

 [Table("TestTable")]
    public class TestTable
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
    }

     [Table("TestTableDetail")]
    public class TestTableDetail
    {
        [Key]
        public int Id { get; set; }
        public int PID { get; set; }
        public string Name { get; set; }
    }

四、创建DbContext上下文

/// <summary>
/// 自定义 数据上下文
/// </summary>
public class MyDbContext : DbContext
{
    public DbSet<TestTable> TestTables { get; set; }
    public DbSet<TestTableDetail> TestTableDetails { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        //写入连接字符串
       optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
    }
}

DbContext是EF操作数据库的窗口,我们将为每个表来创建一个DbSet<>泛型类属性,用来操作具体的表对象;DbSet支持Linq操作;这里两个知识点:

1.如何配置连接字符串

如果是Asp.net Core程序,通常配置在Startup.cs中,需要导入 Microsoft.Extensions.Configuration 名命空间方可使用,按如下方式进行注册

public void ConfigureServices(IServiceCollection services) { services.AddDbContext<BloggingContext>(options =>       options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase"))); 
}

看下源码
EFCore.SqlServer

public static DbContextOptionsBuilder UseSqlServer(
            [NotNull] this DbContextOptionsBuilder optionsBuilder,
            [NotNull] string connectionString,
            [CanBeNull] Action<SqlServerDbContextOptionsBuilder> sqlServerOptionsAction = 
null)
        {
            Check.NotNull(optionsBuilder, nameof(optionsBuilder));
            Check.NotEmpty(connectionString, nameof(connectionString));
            var extension = 
(SqlServerOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString);          
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
            ConfigureWarnings(optionsBuilder);
            sqlServerOptionsAction?.Invoke(new 
SqlServerDbContextOptionsBuilder(optionsBuilder));
            return optionsBuilder;
        }

DbContextOptionsBuilder进行扩展,提供了UseSqlServer方法,连接信息的提供都是通过 DbContextOptionsBuilder 来实现

**针对WinForms以及WPF应用呢?**我测试验证的就是控制台应用

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
     //写入连接字符串
     optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
}

这里我是固定了连接字符串,可以根据配置文件来写入了;可以看到也是对 DbContextOptionsBuilderUseSqlSerer方法的调用;
查看源码:
DbContext

//定义虚方法OnConfiguring的位置
protected internal virtual void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}

InternalServiceProvider中进行了初始化调用,调用了OnConfiguring,从而进行了连接字符串的赋值;
在这里插入图片描述

2.是否需要为每个类都定义DbSet属性

如果业务系统过大,我们真的会定义一个DbContext,然后将所有Entity定义成DbSet<>?应该不会,这时我们可以通过反射来实现;

  1. 通过实现一个反射读取类,来动态读取实体类,也就是读取类具备 “Table”属性的目标类,或者自己集成一个父类用来识别实体类;
  2. 将读取到的实体类,动态加入到DbContext的实体模型中;

通过 重写 OnModelCreating 方法;微软官方文档地址:https://docs.microsoft.com/zh-cn/ef/core/modeling/
通过调用ModelBuilder.Entity方法直接贴代码:

/// <summary>
/// 自定义 数据上下文
/// </summary>
public class DynamicDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        //写入连接字符串
        optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        var assembly = Assembly.GetExecutingAssembly();
        foreach (Type type in assembly.ExportedTypes)
        {
            if (type.IsClass && type != typeof(EntityBase) && typeof(EntityBase).IsAssignableFrom((Type) type))
            {                
                var method = modelBuilder.GetType().GetMethods().FirstOrDefault(x => x.Name == "Entity");
                if (method != null)
                {
                    method = method.MakeGenericMethod(type);
                    method.Invoke(modelBuilder, null);
               }
            }
        }
        base.OnModelCreating(modelBuilder);
    }
}

整体思路还是两步走,先找到实体的实现类,然后通过调用DbContenxtEntity方法;我们来看下DbContext源码;
在这里插入图片描述
最后通过Metadata.AddEntityType加入到实体模型,Metadata用来存储实体元数据;
还有两外一种实现方式,其实也就是衍生的方式了,因为查看源码得知最后实体被加入到了Model,那何不直接加入呢?
在这里插入图片描述
调用代码:

var myDbContext = new DynamicDbContext();
var list = myDbContext.Set<TestTable>().ToList();
Console.WriteLine($"TestTable Count: {list.Count}");
if (!list.Any()) return;
Console.WriteLine($"TestTable Detail ----------------  ");
foreach (var item in list)
{
    Console.WriteLine($"ID : {item.Id} , Name : {item.Name}");
}
Console.WriteLine($"------------------------");

来看下执行效果吧…
在这里插入图片描述
这里的实现让我想到了ABP数据仓储的实现,ABP为每个实体创建一个仓储对象,不需要手动一个个创建,可以查看我的ABP系列 => ABP 数据访问 - IRepository 仓储 ,可以参考ABP仓储管理的思想;大家也可以去看下

五、数据访问

好了,回到最初的实现思路上,前面的准备工作都做的差不多了,该正式跑一把数据了…

public static void Query_查询数据_全量查询()
{
            var myDbContext = new MyDbContext();
            var list = myDbContext.TestTables.ToList();
            Console.WriteLine($"TestTable Count: {list.Count}");            
            if (!list.Any()) return;
            Console.WriteLine($"TestTable Detail ----------------  ");
            foreach (var item in list)           
            {
                Console.WriteLine($"ID : {item.Id} , Name : {item.Name}");
            }
            Console.WriteLine($"------------------------");
}

通过控制台应用,执行上述方法,即可查询到TestTable中的数据

到此我们基本就开始使用EF Core,实现了数据访问;后续将开始对EF的其他使用持续进行分析,以及一些高阶应用;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值