C# 实体框架 - 按名称获取实体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12455389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:20:12  来源:igfitidea点击:

Entity framework - get entity by name

c#entity-frameworkreflection

提问by user1209216

I have the following code (example):

我有以下代码(示例):

public dynamic GetData(string name) 
{
    using(var ctx = GetObjectContext()) 
    {
        switch (name) 
        {
        case "entity1":
            return ctx.entity1.ToList();
        case "entity2":
            return ctx.entity2.ToList();
        ......
        default:
            return null;
        }
    }
}

I want to avoid switch in this sample. How can I find needed entity class by name, call the ToList() method and return data? Can I do this using reflection? Can you help me?

我想避免在此示例中切换。如何按名称找到所需的实体类,调用 ToList() 方法并返回数据?我可以使用反射来做到这一点吗?你能帮助我吗?

采纳答案by chiccodoro

You can do it using reflection, however you will also need to use generics because the type of list returned by the ToList() method is different for each entity type.

您可以使用反射来实现,但是您还需要使用泛型,因为 ToList() 方法返回的列表类型对于每个实体类型都是不同的。

You can access a property getter through reflection like so:

您可以通过反射访问属性 getter,如下所示:

var enumerable = typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null);

Whereas [ClassNameOfContext]is the name of the class that ctx is an instance of. This is not obvious from your code, but you know it :-)

[ClassNameOfContext]是 ctx 是其实例的类的名称。这从您的代码中并不明显,但您知道:-)

The problem is that enumerablewill be an objectand has to be casted to IEnumerable<EntityType>where EntityTypeis the type of entity you are accessing. In other words, it depends on the name you are passing. If you use generics to determine the type, you will be able to properly cast the object and don't have to return a dynamiceven.

问题是,enumerable将是一个object并已被铸造到IEnumerable<EntityType>哪里EntityType是实体的,你正在访问的类型。换句话说,这取决于您传递的名称。如果您使用泛型来确定类型,您将能够正确地转换对象并且不必返回dynamic偶数。

public TEntity Get<TEntity>(string name)
{
    ...

and transform the line from above:

并从上面转换线:

var enumerable = (IEnumerable<TEntity>)(typeof([ClassNameOfContext]).GetProperty(name).GetValue(ctx, null));
return enumerable.ToList();

here you go!

干得好!

Addendum: You could, conceivably, get rid of the string parameter, too - having names of types or properties in strings should be avoided where possible because it is not type safe. The compiler does not recognize it, and IDE features such as refactorings don't account for it. The problem here is that the property names are usually the pluralized form of the entity type names. But you could use reflection to find the property whose type matches the TEntity. I leave this as an exercise :-)

附录:可以想象,您也可以摆脱字符串参数 - 应尽可能避免在字符串中使用类型或属性的名称,因为它不是类型安全的。编译器无法识别它,并且 IDE 功能(例如重构)没有考虑到它。这里的问题是属性名称通常是实体类型名称的复数形式。但是您可以使用反射来查找类型与TEntity. 我把它留作练习:-)

回答by Oleg Polezky

You can use code like this

你可以使用这样的代码

private IEnumerable<TEntity> GetList<TEntity>(string connectionString, Func<object, T> caster)
{
    using (var ctx = new DbContext(connectionString))
    {
        var setMethod = ctx.GetType().GetMethod("Set").MakeGenericMethod(typeof(T));

        var querable = ((DbSet<object>)setMethod
        .Invoke(this, null))
        .AsNoTracking()
        .AsQueryable();

        return querable
            .Select(x => caster(x))
            .ToList();
    }
}

To call like this:

像这样调用:

var branchList = GetList<Branch>("connectionStringName", x => (Branch)x);

You can remove .AsNoTracking() and remove .ToList(), then you will get pure IQueryable which you can query further.

您可以删除 .AsNoTracking() 并删除 .ToList(),然后您将获得可以进一步查询的纯 IQueryable。