• 欢迎光临~

【EF Core 6.0 】连接Sqlite3

开发技术 开发技术 2022-10-14 次浏览

概览

EF Core 6.0 是建立在ADO.NET框架之上的,它下面仍旧使用了ADO.NET方法和类来执行数据操作。DbContext负责将sqlite翻译成sqlite,跟踪数据状态。

EF Core  6.0底层是Miscrosoft.Data.sqlite。DbContext,这个类是EF Code First的核心,在高层次上是数据库抽象,DbContext是一级缓存。DBSet类表示一个实体的集合,用来创建、更新、删除、查询操作,DBSet<TEntity>是DBSet的泛型版本,可以使用DbContext获取DBSet的引用,例如dbContext.PersonInfos

 

【EF Core 6.0 】连接Sqlite3

DbSet与DbContext数据更新奥秘

将实体映射到数据表格方式有两种:特性和Fluent API

实体特性(Data Annonation  标注)

学习顺序

1、了解ORM概念、POCO 类型、linq、mvvm模式

2、了解EF Core 6.0的历史、为什么要使用EF Core、Entity Framework的三种开发风格

3、了解DbSet与DbContext、模型、配置模型

4、DbSet crud操作 ,详细查看https://learn.microsoft.com/zh-cn/ef/core/performance/advanced-performance-topics?tabs=with-di%2Cwith-constant#dbcontext-pooling

5、了解EF Core 6.0 的性能极限

 

开始实操(CodeFirst的数据库初始化)

1)环境:vs2022+.net6.0+EF Core 6.0 +sqlite3+mvvm模式

2)创建WPF应用程序MvvmDemo并且安装实体框架 NuGet 包 Microsoft.EntityFrameworkCore.qlite(6.0.9)、安装 Sqlite 包后,并且安装Microsoft.EntityFrameworkCore 基础包。可以选择安装 Microsoft.EntityFrameworkCore.Proxies 包提供对“延迟加载”数据的支持。

【EF Core 6.0 】连接Sqlite3

 

3)创建sqlite数据库Data.db和PersonInfo表

【EF Core 6.0 】连接Sqlite3【EF Core 6.0 】连接Sqlite3

 

 

 

4)C# 创建实体模型 PersonInfo.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;

namespace MvvmDemo.Mvvm.Models
{
    public class Student
    {
        [Key]
        public string Name { get; set; }
        public string Age { get; set; }
    }
    public class PersonInfo : IDataErrorInfo
    {
        /// <summary>
        /// 对应数据库中 表格
        /// </summary>
        /// 
        #region 实体 
        private string? _email; //字段不会有映射到数据库的表格
        private string? _firstName;
        private string? _lastName;

        [Column("Company")]   //对应数据库中表的列
        public string? Company { get; set; }

        [Column("FirstName")]   //对应数据库中表的列
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = value;
            }
        }

        [Column("LastName")]  //对应数据库中表的列
        public string? LastName
        {
            get { return _lastName; }
            set
            {
                _lastName = value;
            }
        }

        [Column("Email")]  //对应数据库中表的列
        [Key]//主键
        public string Email { get; set; }

        [Column("IsCompany")]  //对应数据库中表的列
        public bool IsCompany { get; set; } = false;

        [Column("TotalSales")]  //对应数据库中表的列
        public double? TotalSales { get; set; }

      
        #endregion

        //不映射到对应数据库中表的列
        public bool IsValid
        {
            get
            {

                foreach (string item in ValidationProperties)
                {
                    if (string.IsNullOrEmpty(ValidationError(item)))
                        return true;

                }

                return false;
            }
        }
        [NotMapped]  //不映射到对应数据库中表的列
        public string? IsSelected { get; set; }

        public PersonInfo()
        {

        }

        string IDataErrorInfo.Error => throw new NotImplementedException();//用于表格的行验证

        //用于单元格属性验证
        string IDataErrorInfo.this[string propertyName] => ValidationError(propertyName);

        private string? ValidationError(string propertyName)
        {
            //哪些属性需要验证
            if (Array.IndexOf(ValidationProperties, propertyName) < 0) return null;

            switch (propertyName)
            {
                case "FirstName":
                    return ValidationFirstName();

                case "LastName":
                    return ValidationLastName();

                case "Company":
                    return ValidationCompany();

                case "Email":
                    return ValidationEmail();



                default: return "";


            }
        }

   
      
        private string? ValidationEmail()
        {
            if (String.IsNullOrEmpty(_email)) return GetPropertyValue("EmailIsNotNull");
            string partn = @"^(?!.)(""([^""r\]|\[""r\])*""|([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!.).)*)(?<!.)@[a-z0-9][w.-]*[a-z0-9].[a-z][a-z.]*[a-z]$"; ;
            if (!Regex.IsMatch(_email, partn, RegexOptions.IgnoreCase))
            {
                return GetPropertyValue("EmailFormatIsError");
            }
            return null;

        }

        private string ValidationCompany()
        {
            throw new NotImplementedException();
        }

        private string? ValidationLastName()
        {
            //本地化错误提示
            if (String.IsNullOrEmpty(_firstName)) return GetPropertyValue("FirstName_NameIsNotnull");
            if (_firstName.Length <= 5) return GetPropertyValue("FirstName_NameLengthMore5char");
            return null;

        }
        static readonly string[] ValidationProperties =
        {
            "Email",
            "FirstName",
            "LastName",

        };
        private string ValidationFirstName()
        {
            //本地化错误提示
            if (String.IsNullOrEmpty(_firstName)) return GetPropertyValue("FirstName_NameIsNotnull");
            if (_firstName.Length <= 5) return GetPropertyValue("FirstName_NameLengthMore5char");
            return "";


        }
        string GetPropertyValue(string name)
        {

            return (string)Application.Current.Resources[name];
        }

        private Dictionary<String, List<String>> errors = new Dictionary<string, List<string>>();

        public PersonInfo(string firstName, string? lastName, string email, bool isCompany, double? totalSales)
        {
            FirstName = firstName;
            LastName = lastName;
            Email = email;
            IsCompany = isCompany;
            TotalSales = totalSales;
       
        }
    }
}

 5)配置数据连接 App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings >
        <!--相对与当前目录的路径-->
        <add name="LoginString"
            connectionString="Data Source=D:程序开发观察者mvvmdemoMvvmDemoMvvmDemoRepositoriesData.db; "
            providerName="Microsoft.EntityFrameworkCore.Sqlite" />

    </connectionStrings>
</configuration>

 

6)建立实体和数据库表格映射。

     有两种方式建立实体和数据表格之间映射关系。

在自定义的上下文DataContext  中采用Fluent API方式建立实体和数据库表格映射关系。详细查看微软官网   FluentAPI详细用法

在实体中通过Attribute特性建立实体和数据库表格映射关系。详细查看微软官网

定制DataContext 上下文,模型映射(Model Mapping),用于连接数据和poco

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Sqlite;
using MvvmDemo.Mvvm.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MvvmDemo.Repositories
{
    public class DataContext : DbContext
    {
        private readonly string _connection;
        public DbSet<PersonInfo> PersonInfos{get;set;}//实体表,提供给外部crud使用,PersonInfos内部有DataContext 的实例
        public DataContext()
        {
         //1、获取连接数据库的字符串
            _connection = ConfigurationManager.ConnectionStrings["LoginString"].ConnectionString;
        }
        //2、联接数据库
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite(_connection);
        }
        //3、建立实体和数据库表格 一 一 映射。  
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<PersonInfo>()
                .ToTable("PersonInfos");
        }
    }
}

7)可选配置.Net EF中DbContext动态生成DbSet

平时我们在使用EF的过程中,都是有DbContext中每一个表加一个DbSet,如果我们一个项目有上千个表,就得加上千个DbSet,是很麻烦的一个工程,现在采用一个简单的方法处理,在DbContext类的OnConfiguring方法中加上如下代码:

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))
                {
                    var method = modelBuilder.GetType().GetMethods().Where(x => x.Name == "Entity").FirstOrDefault();

                    if (method != null)
                    {
                        method = method.MakeGenericMethod(new Type[] { type });
                        method.Invoke(modelBuilder, null);
                    }
                }
            }

            base.OnModelCreating(modelBuilder);
        }

动态加载,不用再一个一个写了,简单方便

 

 

 

平时我们在使用EF的过程中,都是有DbContext中每一个表加一个DbSet,如果我们一个项目有上千个表,就得加上千个DbSet,是很麻烦的一个工程,现在采用一个简单的方法处理,在DbContext类的OnConfiguring方法中加上如下代码:

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))
                {
                    var method = modelBuilder.GetType().GetMethods().Where(x => x.Name == "Entity").FirstOrDefault();

                    if (method != null)
                    {
                        method = method.MakeGenericMethod(new Type[] { type });
                        method.Invoke(modelBuilder, null);
                    }
                }
            }

            base.OnModelCreating(modelBuilder);
        }

动态加载,不用再一个一个写了,简单方便

程序员灯塔
转载请注明原文链接:【EF Core 6.0 】连接Sqlite3
喜欢 (0)
违法和不良信息举报电话:022-22558618 举报邮箱:dljd@tidljd.com