5

我正在考虑创建一段代码,以允许我根据字符串类名动态查询我的数据库。

我在这里想要的简要概述:

我的背景:

public class MyContext : DbContext
{
    public DbSet<Foo> Foos {get;set;}
    public DbSet<Bar> Bars {get;set;}
}

通过我所拥有的设置,我通过执行基本操作来查询此上下文,context.Foos.Where(...) 并且我基本上也想做同样的事情,但不必.Foos在编译时知道该部分,而是希望在运行时完成。

逻辑上我想要的是:

var results = context."ClassName".Where(...)

我试图用一个通用的方法来做到这一点,比如:

//method in context
public IEnumerable<T> GetGenericData<T>() where T : Type
{
    return context.Set<T>();
}

//call in repo
context.GetGenericData<Type.GetType("Foo")>();

不确定我是否在这里走对了路。理想情况下,我想获得一个解决方案,这意味着我不必走 SQL 路线

编辑:一直在努力,我已经到了这一点。

//method in context
public DbSet GetGenericData(Type _type)
{
    return context.Set(_type);
}

//calling like
var data = context.GetGenericData(myType);

现在的问题是,它var data是一个 DbSet。我需要能够将其转换为在运行时定义的类型列表。有没有一个简单的解决方案来做到这一点,因为我不能简单地做var data = context.GetGenericData(myType).toList()

Edit2:为了给问题添加更多上下文,我正在考虑创建一段代码来从文件中读取数据库表的列表,例如,获取这些表中的数据并将其序列化为 XML 文件。

基本上我会有一个包含以下内容的文件:

Foo
Bar
MoreStuff

然后读取它,并将 Foo 表中的所有数据导出到一个名为 Foo.xml 的 xml 文件中。还必须做相反的事情,它从 xml 文件中读取数据并将其导入数据库

4

2 回答 2

6

如果您在运行时不知道实体类型但具有类型名称,则可以借助反射 Type.GetType(string typeName) 按名称获取类型并使用 DbContext.Set 重载,例如 -> DbSet Set.Set(Type type)

更多详细信息,请访问http://msdn.microsoft.com/en-us/library/gg679544(v=vs.113).aspx

更新:

void Main()
{
    var typeMapping = new Dictionary<Type, Func<object, dynamic>>(){
        {typeof(A), a => (A)a}
    };
    var array = new[]{new A(){ o = new Object() },new A(){ o = new Object() },new A(){ o = new Object() },new A(){ o = new Object() },};    
    var objectArray = array.OfType<object>();
    objectArray.Select(a => typeMapping[a.GetType()](a)).Dump();

}

class A{
    public object o {get;set;}
}

这是来自 LinqPad 的示例。你的问题是关于动态编程,我不明白目的,但仍然。在此粘贴中,您必须为所有实体类型(如 CLR 类型和返回所需类型的引用的转换操作)定义类型映射。数组变量是例如用途,objectArray 是您的数据。

更新2:

使用 SerializableAttribute http://msdn.microsoft.com/en-us/library/system.serializableattribute(v=vs.110).aspx标记您的实体类型,而 不是调用 ToList 或 ToArray 扩展名

var data = context.GetGenericData(myType).Tolist();

并使用 XmlSerializer 对其进行序列化

var fileStream = File.OpenWrite("someFilePathName");
new XmlSerializer().Serialize(fileStream, data);

而已!它会起作用,因为 CLR 会确切地知道 DbSet 集合中的项目类型。而且你不必投给任何人。然后 XmlSerializer 将完成序列化器实体集合所需的所有工作,并将其写入流,即文件流。另一件事是添加一些检查并为 IDisposable 实例添加 using 块。

更新3:

DbSet 不能使用 ToList 强制转换为精确类型,因为这个想法是避免在实体的编译时使用类型。所以这是加载数据并将其转换为对象以继续操作的想法

Set(typeof(TableBase)).Load();
var collectionToExport = Set(typeof (TableBase)).Local.Cast<object>().ToList();

一起:

var type = Type.GetType("Foo");
context.Set(type).Load();
var collectionToExport = context.Set(type).Local.Cast<object>().ToList();
var fileStream = File.OpenWrite("someFilePathName");
new XmlSerializer().Serialize(fileStream, data);
于 2013-11-14T09:49:56.123 回答
0

您的方法很可靠,但是我会重新考虑该IEnumerable方法,因为它不支持Include其他数据库特定操作。

于 2013-11-14T09:39:14.257 回答