我正在创建一段代码,允许我根据字符串类名动态查询数据库。
我想要的简要概述:
我的背景:
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。我需要能够将其转换为在运行时定义的Type列表。有没有一个简单的解决方案来做到这一点,因为我不能简单地做var data = context.GetGenericData(myType).toList()
EDIT2: 要为问题添加更多上下文,我正在创建一段代码来从文件中读取数据库表,例如,获取这些表中的数据并将其序列化为XML文件。
基本上我会有一个包含以下内容的文件:
Foo
Bar
MoreStuff
然后将读取,并将Foo表中的所有数据导出到名为Foo.xml的xml文件中。还必须进行相反的操作,其中从xml文件中读取数据并将其导入数据库
答案 0 :(得分:6)
如果您在运行时不知道实体类型但具有类型名称,则可以在反射Type.GetType(字符串typeName)的帮助下按名称获取类型,并使用DbContext.Set重载,如 - &gt; DbSet Set.Set(类型类型)
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是您的数据。
UPADATE2:
使用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实例添加使用块。
UPDATE3:
无法将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);
答案 1 :(得分:0)
您的方法很可靠,但我会重新考虑IEnumerable
方法,因为它不支持Include
和其他特定于数据库的操作。