【问题标题】:How do I select correct DbSet in DbContext based on table name如何根据表名在 DbContext 中选择正确的 DbSet
【发布时间】:2014-10-10 18:24:18
【问题描述】:

假设我有一个带有以下 DbSet 的 DbContext

class Amimals : DbContext
{
    public DbSet<Dog> Dogs { get; set; }
    public DbSet<Cat> Cats { get; set; }
}

在每个 EntityTypeConfiguration 内部,我都在为每个 DbSet 定义表

class DogConfig : EntityTypeConfiguration
{
    public DogConfig()
    {
        this.ToTable("DOG_TABLE");
        ...
    }
}

现在,如果我有表名和 DbContext,我该如何获取和使用正确的 DbSet?

void foo()
{
    string tableName = this.GetTableName();
    using(Animals context = new Animals())
    {
        /* Made up solution */
        DbSet animalContext = context.Where(c => c.TableName == tableName);
        ...
        /* Do something with DbSet */
        ...
    }
}

【问题讨论】:

    标签: c# linq entity-framework reflection


    【解决方案1】:

    您可以通过Type 使用DbContext.Set(Type entityType) 方法从DbContext 获取DbSet。因此,如果您将模型类名称作为字符串,您应该对实际的 clr 类型进行一些映射。

    例如:

    string tableName = "Cat";
    var type = Assembly.GetExecutingAssembly()
            .GetTypes()
            .FirstOrDefault(t => t.Name == tableName);
    
    DbSet catContent;
    if(type != null)
        catContext = context.Set(type);
    

    您还可以使用 Full Assembly Qualified Name Type.GetType(' ... ') 从字符串中获取类型

    如果您可以以某种通用方式存储配置并使用通用context.Set&lt;T&gt;() 方法,将会更容易。

    【讨论】:

    • 嗯,这是返回 EntityTypeConfiguration 类。我需要使用 DbSet。有没有办法在上下文中获取 DbSet 的实例?
    • 是的,你可以。这段代码工作得很好,并返回 DbSet 的一个实例。在我的示例中,“talbeName”必须与模型类名称匹配。请注意,“tableName”等于“Cat”,因此结果将是 DbSet。好的,“tableName”听起来有点不清楚,它应该是“c# 模型类名称,它在 DbContext 通用 DbSet 中使用这种类型并代表一些表名”。请分享您的无效代码。
    • 好吧,如果我说context.Cats.Select(c =&gt; c) 我尝试使用AsQueryable(),但我仍然无法将Linq 方法调用到DbSet 中
    • msdn.microsoft.com/en-us/library/… 表示context.Set(type) 返回一个非通用 DbSet 实例。如果我键入context.Set&lt;Cat&gt;(),我实际上可以为返回的 DbSet 调用 linq 方法。有没有办法可以使用&lt;&gt; 方式?
    • 旁注:虽然这种方法在 Entity Framework 上运行良好,但它不适用于 Entity Framework Core对于 EF Core 我发现 this approach 非常有用。希望其他人也能发现此评论有用!
    【解决方案2】:

    下面是另一种方法,对我来说效果很好:

    Type t = Type.GetType(Assembly.GetExecutingAssembly().GetName().Name + "." + "TableName");
    DbSet dbset = dbcontext.Set(t);
    

    【讨论】:

    • 错误 CS0411:无法从用法推断方法“方法”的类型参数。尝试明确指定类型参数。
    • @Amir978 您正在使用Entity Framework Core (EF Core)。问题是关于Entity Framework(可能是EF 6)。
    【解决方案3】:

    在 DotNetCore 中,我做了类似的事情。在这种情况下,最好使用白名单来确保某人不会要求不受欢迎的实体。

        [HttpGet]
        [Route("entities/{entityName}")]
        public IActionResult GetEntities(string entityName)
        {
            var name = Assembly.GetExecutingAssembly().GetName().Name + ".path.to.your.entity." + entityName;
            Type entityType = Type.GetType(name);
            var results = _myContext
                .GetType()
                .GetMethod("Set")
                .MakeGenericMethod(entityType)
                .Invoke(_myContext, null);
            return Ok(results);
        }
    

    【讨论】:

    • 感谢您的回答,我试过了,但 entityType 为 Null,所以下一行抛出错误:System.Reflection.AmbiguousMatchException Ambiguous match found
    • @Amir978 只是猜测,但您可能在不同的空间中有两个同名的类。
    • @Amir978 没有问题是因为有两个 Set 方法。 Set() 和 Set(string) 对我有用的是查询: ...GetMethods().First(e => e.Name == "Set" && e.IsGenericMethod)
    猜你喜欢
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    相关资源
    最近更新 更多