简体   繁体   English

如何使用 EFCore 3.1 从 DbContext 中选择特定的 DbSet?

[英]How do I choose a particular DbSet from a DbContext using EFCore 3.1?

My app works with 5 tables right now, maybe more in the future, and I would like to minimize code duplication.我的应用程序现在可以使用 5 个表,将来可能会更多,我想尽量减少代码重复。 One example below is for Swd0004 and I also have the same code for Swd0013, and other duplicated functions for each table.下面的一个示例是针对 Swd0004 的,我对 Swd0013 也有相同的代码,以及每个表的其他重复函数。 The user chooses what table to work with from a drop down box.用户从下拉框中选择要使用的表。 I'd like to take this drop down box selection and somehow pass that to the functions.我想采用这个下拉框选择并以某种方式将其传递给函数。

private void SWD_0004_Lookup()
{
    using (var ctx = new EFContext())
    {
        var query = ctx.Swd0004;
        var readList = query.ToList();
        Debug.WriteLine("QUERY COUNT: " + readList.Count);
        // create datatable from query results so I can populate datagridview
        var dt = LINQResultToDataTable(query);
        dgvQueryResults.DataSource = dt;
        GetColumnHeaders(dt);
        DataDT = dt; // copy local dt so we can use DataDT for getting record data
    }
}

This is a database first app.这是一个数据库优先的应用程序。 Swd0004 is a table in a database and therefore a DbSet in my EFContext class. Swd0004 是数据库中的一个表,因此是我的 EFContext class 中的一个 DbSet。 My Swd0004 class:我的Swd0004 class:

namespace SWDDB.Models
{
    public partial class Swd0004
    {
        public int Id { get; set; }
        public string PartNumber { get; set; }
...

Then do I need to add a generic to it to implement @abdusco answer?那么我是否需要为其添加一个泛型来实现@abdusco 答案? Maybe I'm not familiar enough with generics.也许我对 generics 不够熟悉。

    public partial class Swd0004<TEntity> : ??? where TEntity : class

Here's another example:这是另一个例子:

private List<Swd0004> ConvertDT(DataTable dt)
{
    var importList = new List<Swd0004>();
    // convert DataRow object to SWD object, otherwise BulkInsert will fail
    foreach (DataRow row in dt.Rows)
    {
        var obj = CreateItemFromRow<Swd0004>(row);
        // BulkInsert needs a list
        importList.Add(obj);
    }
    return importList;
}

As you can see, I have to explicitly state Swd0004 three times.如您所见,我必须明确 state Swd0004 三次。 So I would have to duplicate this function for each table, 5 times.所以我必须为每个表复制这个 function 5 次。

UPDATE I'm trying to implement what @bolkay suggested. UPDATE我正在尝试实施@bolkay 的建议。 I created this class:我创建了这个 class:

using SWDDB.Models;
using System.Diagnostics;
using System.Linq;

namespace SWDDB
{
    public abstract class BaseLookup<TEntity> where TEntity : class
    {
        public virtual void PerformLookup()
        {
            using (var ctx = new EFContext())
            {
                var query = ctx.Set<TEntity>();
                Debug.WriteLine("QUERY COUNT: " + query.ToList().Count);
            }
        }
    }
    public class SWD0004Lookup : BaseLookup<Swd0004>
    {
        
    }
}

It feels like I'm close but I can't figure out how to call PerformLookup from my mainline code.感觉就像我很接近,但我不知道如何从我的主线代码中调用 PerformLookup。

I don't fully understand the logic behind users selecting a table to work with.我不完全理解用户选择要使用的表背后的逻辑。

You can do something like this as a starting point to remove duplication of methods.您可以这样做作为起点来删除方法的重复。

Create a base class with the logic.使用该逻辑创建一个基础 class。

    public abstract class BaseLookUp<TEntity> where TEntity : class
    {
        public virtual void PerformLookup()
        {
            using (var ctx = new EFContext())
            {
                var query = ctx.Set<TEntity>();
                //etc...
            }
        }
    }
    public class SWD004Lookup : BaseLookUp<SWD004004>
    {

    }

Totally depending on your needs, you could just make it a static method etc.完全取决于您的需要,您可以将其设为 static 方法等。

You can get a DbSet using DbContext.Set<TEntity>() instead of using properties in your EfContext class: 您可以使用DbContext.Set<TEntity>()获取DbSet而不是使用EfContext class 中的属性:

private void SWD_Lookup<TEntity>() // <-- turn it into a generic method
{
    using (var ctx = new EFContext())
    {
        var query = ctx.Set<TEntity>(); // <-- get dbset by passing the type
        // ...
    }
}

then you can call it like this:那么你可以这样称呼它:

SWD_Lookup<Swd0004>();
SWD_Lookup<Swd0013>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM