首页 > 数据库 >Entity Framework教程-数据库上下文对象(Data Context)

Entity Framework教程-数据库上下文对象(Data Context)

时间:2022-10-15 09:25:43浏览次数:98  
标签:Console WriteLine item db Entity Framework Context new PandaContext

更新记录
转载请注明出处:
2022年10月15日 发布。
2022年10月10日 从笔记迁移到博客。

DbContext对象介绍(数据库上下文对象)

数据库上下文对象说明

A DbContext instance represents a session with the database and can be used to query and save instances of your entities

DbContext is a combination of the Unit Of Work and Repository patterns

DbContext 类是EF Core的核心

一个DbContext实例代表一个与数据库的会话(session)

可以用于查询和保存数据到数据库

注意:DBContext不是一个线程安全的对象(thread safe object)

DbContext主要功能

Manage database connection(管理数据库连接)

Configure model & relationship(配置模型和模型之间的关系)

Querying database(查询数据库的数据)

Saving data to the database(保存数据到数据库)

Configure change tracking(管理变化跟踪)

Caching(缓存)

Transaction management(事务管理)

DbContext使用

DbContext类型定义

使用DbContext类型需要创建一个继承其的子类

通常包含 DbSet 属性,用来引用实体模型

public class PandaDbContext : DbContext
{
    //无参数的构造函数
    public PandaDbcontext()
    {

    }

    //有参数的构造函数
    public PandaDbcontext(DbContextOptions<PandaDbcontext> dbContextOptions) : base(dbContextOptions)
    {

    }

    //配置Dbcontext
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    }

    //配置模型,比如FluentAPI
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }

    //实体模型
    public DbSet<Student> Students { get; set; }
    public DbSet<Course> Courses { get; set; }
}

待完善:https://docs.microsoft.com/en-us/ef/core/dbcontext-configuration/

如何使用OnConfiguring

DbContext对象实例化

因为DbContext会占用一定的资源最好使用后就进行释放

using(DbContext db = new DbContext())
{
    //保存修改
    db.SaveChanges();
    //保存修改(异步)
    db.SaveChangesAsync();
}

Database属性

说明

Database属性用于提供数据库的管理支持,如连接、命令和事务

这个属性在数据库上实现了一个facade

返回一个System.Data.Entity.Database对象

常用方法使用

using(Model1 model = new Model1())
{
    //获得database对象
    System.Data.Entity.Database database = model.Database;

    //获得执行的SQL记录
    //注意:这是一个委托,参数为string,无返回值
    database.Log = Console.WriteLine;

    //获得连接信息
    var conn = database.Connection;
    //获得连接字符串
    Console.WriteLine(conn.ConnectionString);
    //获得连接的状态
    Console.WriteLine(conn.State);
    //获得连接的数据库服务器
    Console.WriteLine(conn.DataSource);
    //获得连接的数据库
    Console.WriteLine(conn.Database.ToString());
    //获得连接到的服务器版本
    Console.WriteLine(conn.ServerVersion);
}

进行数据库的直接增删改查

using(PandaContext db = new PandaContext())
{
    //SQL查询
    var queryResult = db.Database.SqlQuery<Product>("SQL语句", new Object[3] {
        new SqlParameter("@abc1","Value"),
        new SqlParameter("@abc2","Value"),
        new SqlParameter("@abc3","Value")
    });

    //SQL增删改
    db.Database.ExecuteSqlCommand("SQL语句");
}

ContextId属性

每个上下文都有一个唯一的id(unique id)

Model属性

Model属性保存数据库中映射的基础实体和关系的元数据

ChangeTracker属性

变化追踪器

可用于确定是否启用了LazyLoading以及上下文实体是否有更改

并可用于操作,如接受更改和级联删除

常用方法

Method Purpose
Add/AddAsync Allows insertion of the entity into the database
AddRange/AddRangeAsync
Find/FindAsync Find a specific entity by Id
OnConfiguring Allows for us to override the options
OnModelCreating Allows us to use the to further define our entities and their relationships
Remove Delete an entity from the database
SaveChanges/ SaveChangesAsync Apply the tracked changes in a single transaction
Update Used to perform an update to the tracked entity
Method Usage
Add Adds a new entity to DbContext with Added state and starts tracking it. This new entity data will be inserted into the database when SaveChanges() is called.
AddAsync Asynchronous method for adding a new entity to DbContext with Added state and starts tracking it. This new entity data will be inserted into the database when SaveChangesAsync() is called.
AddRange Adds a collection of new entities to DbContext with Added state and starts tracking it. This new entity data will be inserted into the database when SaveChanges() is called.
AddRangeAsync Asynchronous method for adding a collection of new entities which will be saved on SaveChangesAsync().
Attach Attaches a new or existing entity to DbContext with Unchanged state and starts tracking it.
AttachRange Attaches a collection of new or existing entities to DbContext with Unchanged state and starts tracking it.
Entry Gets an EntityEntry for the given entity. The entry provides access to change tracking information and operations for the entity.
Find Finds an entity with the given primary key values.
FindAsync Asynchronous method for finding an entity with the given primary key values.
Remove Sets Deleted state to the specified entity which will delete the data when SaveChanges() is called.
RemoveRange Sets Deleted state to a collection of entities which will delete the data in a single DB round trip when SaveChanges() is called.
SaveChanges Execute INSERT, UPDATE or DELETE command to the database for the entities with Added, Modified or Deleted state.
SaveChangesAsync Asynchronous method of SaveChanges()
Set Creates a DbSet that can be used to query and save instances of TEntity.
Update Attaches disconnected entity with Modified state and start tracking it. The data will be saved when SaveChagnes() is called.
UpdateRange Attaches a collection of disconnected entities with Modified state and start tracking it. The data will be saved when SaveChagnes() is called.
OnConfiguring Override this method to configure the database (and other options) to be used for this context. This method is called for each instance of the context that is created.
OnModelCreating Override this method to further configure the model that was discovered by convention from the entity types exposed in DbSet properties on your derived context.

增删改查操作

添加数据

using(PandaContext db = new PandaContext())
{
    //新建数据
    PandaTable pandaTable1 = new PandaTable()
    {
        Id = 54088,
        Name = "Dog8899",
        Code = "8899",
        Note = "www.Dog.com"
    };
    //新建数据
    PandaTable pandaTable2 = new PandaTable()
    {
        Id = 54089,
        Name = "Dog8899",
        Code = "8899",
        Note = "www.Dog.com"
    };
    //添加数据(单条)
    db.PandaTable.Add(pandaTable1);
    //添加数据(多条)
    db.PandaTable.AddRange(new PandaTable[] { pandaTable1,pandaTable2 });
    //保存到数据库
    db.SaveChanges();
}

删除数据

//reload
context.Entry(表).Reload();

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id >= 6
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();

    //移除数据(单条)
    if (pandaTables.Count() > 0)
    {
        db.PandaTable.Remove(pandaTables[0]);
    }

    //移除数据(多条)
    db.PandaTable.RemoveRange(queryResult);
    //保存到数据库
    db.SaveChanges();
}

更新/修改数据

更新/修改数据

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();

    //修改数据
    if(pandaTables.Count() > 0)
    {
        pandaTables[0].Name = "NewMonkey";
        pandaTables[0].Note = "NewMonkeyNewMonkeyNewMonkey";
    }

    //保存到数据库
    db.SaveChanges();
}

查询数据-使用LINQ

using(PandaContext db = new PandaContext())
{
    //查找指定数据
    var qureyResult = from item in db.PandaTable
                        where item.Id == 1
                        select item;

    foreach (var item in qureyResult)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Code);
        Console.WriteLine(item.Note);
    }
}

查询数据-使用Find

using(PandaContext db = new PandaContext())
{
    //查找指定的数据使用Find方法
    //注意:参数为表的主键
    //注意:如果有多个主键需要传入多个参数
    PandaTable pandaTable =  db.PandaTable.Find(5);
    //使用数据
    if (pandaTable != null)
    {
        Console.WriteLine(pandaTable.Id);
        Console.WriteLine(pandaTable.Name);
        Console.WriteLine(pandaTable.Code);
        Console.WriteLine(pandaTable.Note);
    }
}

查询数据-执行SQL代码

using(PandaContext db = new PandaContext())
{
    //执行SQL代码
    string sql = "SELECT * FROM PandaTable where Id = @Id";
    //绑定的参数值
    SqlParameter id = new SqlParameter("Id", 5);
    var queryResult = db.PandaTable.SqlQuery(sql, id);
    foreach (var item in queryResult)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Code);
        Console.WriteLine(item.Note);
    }
}

查询的结果转为List和Array

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id >= 6
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();
    //转为Array
    PandaTable[] pandaTables1 = queryResult.ToArray<PandaTable>();
}

获得查询的具体SQL

using(PandaContext db = new PandaContext())
{
    var qureyResult = from item in db.PandaTable
                        where item.Id == 1
                        select item;
    //获得查询的具体SQL
    Console.WriteLine(qureyResult.ToString());
}

重新载入更新后的数据

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();

    //修改数据
    if(pandaTables.Count() > 0)
    {
        pandaTables[0].Name = "666NewMonkey";
        pandaTables[0].Note = "666NewMonkeyNewMonkeyNewMonkey";
    }

    //保存到数据库
    db.SaveChanges();

    //更新完成从新载入更新后的结果
    db.Entry(pandaTables[0]).Reload();

    //再查询数据
    var queryResult2 = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //输出数据
    foreach (var item in queryResult2)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Note);
    }
}

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();

    //修改数据
    if(pandaTables.Count() > 0)
    {
        pandaTables[0].Name = "NewMonkey";
        pandaTables[0].Note = "NewMonkeyNewMonkeyNewMonkey";
    }

    //保存到数据库
    db.SaveChanges();
}

查询数据-使用LINQ

using(PandaContext db = new PandaContext())
{
    //查找指定数据
    var qureyResult = from item in db.PandaTable
                        where item.Id == 1
                        select item;

    foreach (var item in qureyResult)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Code);
        Console.WriteLine(item.Note);
    }
}

查询数据-使用Find

using(PandaContext db = new PandaContext())
{
    //查找指定的数据使用Find方法
    //注意:参数为表的主键
    //注意:如果有多个主键需要传入多个参数
    PandaTable pandaTable =  db.PandaTable.Find(5);
    //使用数据
    if (pandaTable != null)
    {
        Console.WriteLine(pandaTable.Id);
        Console.WriteLine(pandaTable.Name);
        Console.WriteLine(pandaTable.Code);
        Console.WriteLine(pandaTable.Note);
    }
}

查询数据-执行SQL代码

using(PandaContext db = new PandaContext())
{
    //执行SQL代码
    string sql = "SELECT * FROM PandaTable where Id = @Id";
    //绑定的参数值
    SqlParameter id = new SqlParameter("Id", 5);
    var queryResult = db.PandaTable.SqlQuery(sql, id);
    foreach (var item in queryResult)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Code);
        Console.WriteLine(item.Note);
    }
}

查询的结果转为List和Array

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id >= 6
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();
    //转为Array
    PandaTable[] pandaTables1 = queryResult.ToArray<PandaTable>();
}

获得查询的具体SQL

using(PandaContext db = new PandaContext())
{
    var qureyResult = from item in db.PandaTable
                        where item.Id == 1
                        select item;
    //获得查询的具体SQL
    Console.WriteLine(qureyResult.ToString());
}

重新载入更新后的数据

using(PandaContext db = new PandaContext())
{
    //查询数据
    var queryResult = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //转为List
    List<PandaTable> pandaTables = queryResult.ToList<PandaTable>();

    //修改数据
    if(pandaTables.Count() > 0)
    {
        pandaTables[0].Name = "666NewMonkey";
        pandaTables[0].Note = "666NewMonkeyNewMonkeyNewMonkey";
    }

    //保存到数据库
    db.SaveChanges();

    //更新完成从新载入更新后的结果
    db.Entry(pandaTables[0]).Reload();

    //再查询数据
    var queryResult2 = from item in db.PandaTable
                        where item.Id == 5
                        select item;
    //输出数据
    foreach (var item in queryResult2)
    {
        Console.WriteLine(item.Id);
        Console.WriteLine(item.Name);
        Console.WriteLine(item.Note);
    }
}

使用本地数据集

本地数据集说明

当添加/查询数据库的数据时,会在本地的Local数据集中保存一份

通过使用本地数据可以缓解数据库的压力

使用方法

使用数据集的Local方法即可

using(PandaContext db = new PandaContext())
{
    //获得数据库中数据的条数
    db.PandaTable.Count();
    //获得本地DataSet中数据的条数
    db.PandaTable.Local.Count();
}

Local本地数据集数据查询

在ASP.NET Core中将DbContext注入到服务容器中

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

DbContextOptionsBuilder 对象

说明

数据库上下文对象的配置项的配置器

用于生成具体的配置项

检测是否已经配置了配置项

使用IsConfigured属性

获得DBContextOptions对象

使用Options属性

常用方法

Name Method or Extension Purpose
AddInterceptors Method Allows adding a list of interceptors to monitor or modify operations
Configure Warnings Method Used to change runtime behavior of warnings, can impact performance
EnableDetailed Errors Method Used to include detailed error messages generated by exceptions, can impact performance
EnableSensitive DataLogging Method Allows information to be logged that would ordinarily be suppressed, can be a security risk
UseInMemory Database Extension Allows the context to work against an in-memory database
UseLazyLoading Proxies Extension Enables the creation of proxies for lazy loading
UseSqlLite Extension Sets the context to use SQL Lite for the underlying storage.
UseSqlServer Extension Sets the context to use SQL Server for the underlying storage

DBContextOptions对象

说明

数据库上下文对象的配置项对象

常用属性

ContextType

Gets the type for the context, if no type is defined, then DBContext will be returned

Extensions

Gets a list of Extensions as configured, such as the type of database being leveraged

IsFrozen

Used to determine if the Context is open for further configuration.

If true, the system cannot further override the context options in the OnConfiguring method

DataSet

DataSet说明

DataSet数据实体状态

应用程序更改数据对象会引发数据集状态的变更

可能出现的状态有:

Added 添加实体对象创建到实体集中,数据未添加进数据库

Modified 实体对象已经存在于实体数据集中,数据库同时存在对应的数据,但某些实体对象属性值已经变更,未更新到数据库中

Deleted 实体对象已经存在于实体数据集中,数据库同时存在对应的数据,但是实体对象本身被标识为删除

Unchanged 实体对象存在于数据集中,数据库同时包含对应未曾更改的相同数据

Detached 实体对象已经不在数据集中

注意:当实体对象我Added或Modified状态时,调用SaveChanges方法变更数据成功后,状态会调整到Unchanged;当实体对象状态在Deleted时,调用SaveChanges方法后,状态会调整到Detached

注意:每一个数据对象均有其专属的状态,要获得状态信息,可以使用DbContext的Entry方法

使用该方法可以获得每个实体自身的状态

contextObject.Entry(entityTypeObject).State

该属性的类型是一个EntityState枚举值,分别为:

EntityState.Added
EntityState.Modified
EntityState.Deleted
EntityState.Unchanged
EntityState.Detached

实例:

using(PandaModel pandaModel = new PandaModel())
{
    OrderDetail orderDetail = pandaModel.OrderDetail.First();
    //输出状态
    Console.WriteLine(pandaModel.Entry(orderDetail).State);
    pandaModel.OrderDetail.Remove(orderDetail);
    //输出状态
    Console.WriteLine(pandaModel.Entry(orderDetail).State);
    int affectRows = pandaModel.SaveChanges();
    Console.WriteLine("Success! {0}",affectRows);
    //输出状态
    Console.WriteLine(pandaModel.Entry(orderDetail).State);
}

主要方法

Name Method or Extension Purpose
Add Method Add the entity to the context for insert
AsNoTracking Method Gets an entity that is not tracked so that any modifications do not cause concurrency issues
Create Method Creates a new entity for the type T
Find/FindAsync Method Locates an entity by Id and attaches the entity
Include Method Used to fetch related entities
Remove Method Sets the entity as deleted in the context
SqlQuery Method Allows execution of a raw SQL Query
AddOrUpdate Extension Inserts the entity if it does not exist or updates the entity if it does exist

ChangeTracker

说明

变化追踪器

The DbContext in Entity Framework Core includes the ChangeTracker class in Microsoft.EntityFrameworkCore.ChangeTracking namespace

tracking the state of each entity retrieved using the same DbContext instance

实例

实例:获得每个实体的状态

using System;
using ConsoleApp7.Repository;
using ConsoleApp7.Models;
using System.Linq;

namespace ConsoleApp7
{
    class Program
    {
        static void Main(string[] args)
        {
            using(PandaDbContext db = new PandaDbContext())
            {
                Product product = new Product()
                {
                    ProductTitle = "Panda666",
                    Price = 666.66M
                };
                User user = new User()
                {
                    UserTitle = "panda666",
                    age = 8888888
                };
                foreach (var item in db.ChangeTracker.Entries())
                {
                    Console.WriteLine($"{item.Entity} : {item.State}");
                }
                Console.WriteLine("============================================");
                db.Products.Add(product);
                db.Users.Add(user);

                foreach (var item in db.ChangeTracker.Entries())
                {
                    Console.WriteLine($"{item.Entity} : {item.State}");
                }
                //保存设置
                db.SaveChanges();
                Console.WriteLine("============================================");
                db.Products.Remove(db.Products.First());
                foreach (var item in db.ChangeTracker.Entries())
                {
                    Console.WriteLine($"{item.Entity} : {item.State}");
                }
                Console.WriteLine("============================================");
                //保存设置
                db.SaveChanges();
            }
            //wait
            Console.ReadKey();
        }
    }
}

初始化数据

在OnModelCreating中定义初始化数据

HasData方法接收一个可变参数数组

即可以添加一个或多个相同的实体类型

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<Author>().HasData(
        new Author
        {
            Id = new Guid("72D5B5F5-3008-49B7-B0D6-CC337F1A3330"),
            Name = "Author 1",
            BirthDate = new DateTimeOffset(new DateTime(1960, 11,18)),
            Email = "[email protected]"
        },
        //…
    );
}

使用初始化数据扩展类

如果添加的初始数据比较多,建议单独抽出

如果要添加的测试数据比较多,为了保持LibraryDbContext类的简洁清晰

可以为ModelBuilder类创建扩展方法,并在扩展方法中添加数据

定义:

public static class ModelBuilderExtension
{
    public static void SeedData(this ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>().HasData(…);
        modelBuilder.Entity<Book>().HasData(…);
    }
}

使用:

在Context类的OnModelCreating方法中

只需调用扩展方法modelBuilder.SeedData()即可

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.SeedData();
}

标签:Console,WriteLine,item,db,Entity,Framework,Context,new,PandaContext
From: https://www.cnblogs.com/cqpanda/p/16778277.html

相关文章