EF Core中的DbSet <T>属性和Set <T>()函数之间的区别?

Jer*_*oen 3 c# entity-framework-core

在这种情况下:

public class FooContext : DbContext 
{
    public FooContext(DbContextOptions<FooContext> opts) : base(opts)
    { }

    public DbSet<Bar> Bars { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我可以通过Bar两种方式达到目标:

fooContext.Bars.Add(new Bar()); // Approach 1
Run Code Online (Sandbox Code Playgroud)

要么

fooContext.Set<Bar>().Add(new Bar()); // Approach 2
Run Code Online (Sandbox Code Playgroud)

两种方法有什么区别?

我试图通过以下方式回答自己的问题:

但是我找不到关于将两者中的哪一个用于哪个目的的任何很好的解释。有什么不同?或更重要的是:我应该在哪里以及如何在文档中找到它?

Iva*_*oev 7

不幸的是,目前您不会在官方文档中找到解释,主要是因为所有这些在功能上都是等效的。

首先,通用的方法DbConext一样Add<TEntity>Remove<TEntity>Attach<TEntity>等完全等同相应的DbSet<TEntity>方法(实际上目前他们是后来的实施,即DbSet方法只需调用相应的DbContext通用方法)。您使用哪一个只是品味问题。

其次,DbSet<TEntity>属性和Set<TEntity>方法在功能上是等价的,但确实有一些非功能性的差异。

DbSet特性被填充一次在上下文创建,而Set方法始终执行查找,所以DbSet访问属性应该是快于Set方法(虽然不显著)。

重要的区别实际上是 EF Core包含和排除类型约定:

按照惯例,DbSet在您的上下文的属性中公开的类型包含在您的模型中。此外,OnModelCreating方法中提到的类型也包括在内。

因此,虽然您可以保留DbContext未公开的DbSet属性并仅使用Set方法,但如果这样做,您必须通过添加对每个实体类型OnModelCreating的调用来明确告诉 EF Core 您的实体类型modelBuilder.Entity<TEntity>();(这就是文档的含义)方法中提到的类型OnModelCreating)。


cal*_*san 6

他们做的完全一样。真正的问题是,什么时候可以使用另一个。

当您知道要使用的实体类型时,可以使用DbSet。您只需编写DbContext名称,然后输入实体类型名称,然后可以使用可用的实体方法为该实体创建,读取,更新或删除条目。您知道自己想要什么,并且知道在哪里做。

当您不知道要使用的实体类型时,可以使用Set。可以说,您想构建一个类,该类执行您的存储库功能,以创建,读取,更新和删除实体条目。您希望此类可重用,以便您只需在其上传递DbContext即可,并且它将使用相同的create,read,update和delete方法。您不确定要在哪个DbContext上使用它或DbContext将具有什么DbSet。这是您使用泛型的时候,您的类可以被任何DbContext用于任何DbSet。

这是一个类的示例,可用于在任何DbContext中的任何DbSet上创建任何实体

public class Repository<TDbContext> where TDbContext : DbContext
{
    private TDbContext _context { get; }

    public Repository(TDbContext context)
    {
       _context = context;
    }

    public TEntity Create<TEntity>(TEntity entity) where TEntity : class
    {
        if(entity != null)
        {
            var dataSet = _context.Set<TEntity>();

            if(entity is IEnumerable)
            {
                dataSet.AddRange(entity);
            }
            else
            {
                dataSet.Add(entity);
            }

            _context.SaveChanges();


        }

        return entity;
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是如何使用它。

var dbContext01 = new DbContext01();
var dbContext02 = new DbContext02();

var repository01 = new Repository<DbContext01>(dbContext01);
var repository02 = new Repository<DbContext02>(dbContext02);

repository01.Create(new EntityOnDbContext01 {
    Property01A = "String",
    Property01B = "String"
});

repository02.Create(new EntityOnDbContext02 {
    Property02A = 12345,
    Property02B = 12345
});
Run Code Online (Sandbox Code Playgroud)

如果您想了解更多有关泛型的信息,请点击这里。它超级棒。

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/generics/