从类型获取DbSet [英] Get DbSet from type
问题描述
我目前正在使用
Context.GetEntityTypes();
返回表格列表。
现在我需要获取特定类型的数据。我目前的实现是:
//在我的上下文
public IQueryable< dynamic> GetDbSetByType(string fullname)
{
Type targetType = Type.GetType(fullname);
var model = GetType()
.GetRuntimeProperties()
.Where(o =>
o.PropertyType.IsGenericType&&
o.PropertyType.GetGenericTypeDefinition()== typeof(DbSet&)&&
o.PropertyType.GenericTypeArguments.Contains(targetType))
.FirstOrDefault();
if(null!= model)
{
return(IQueryable< dynamic>)model.GetValue(this);
}
返回null;
}
在我的控制器中使用此代码
[HttpGet({requestedContext} / {requestedTable} / data)]
public IActionResult GetTableData(string requestedContext,string requestedTable)
{
var data = Request.Query;
var context = GetContext(requestedContext);
if(context == null)
{
return new ErrorObjectResult(Invalid context specified);
}
var entity = context.GetEntity(requestedTable);
if(entity == null)
{
return new ErrorObjectResult(Invalid table specified);
}
var set = context.GetDbSetByType(entity.ClrType.AssemblyQualifiedName);
if(set == null)
{
返回新的ErrorObjectResult(指定的无效表 - 无法找到DbSet);
}
var start = Convert.ToInt32(data [start]。ToString());
var count = Convert.ToInt32(data [length]。ToString());
var search = data [search [value]];
返回新的ObjectResult(set.SKip(start).Take(count));
}
就这样,这将返回长度计数
和位置开始
。但是,我无法对 IQueryable< dynamic>
的特定属性执行查询。
问题是: p>
- 这似乎是一件简单的事情,所以我几乎肯定我错过了一些事情 - 这很容易做到。
- 如果不是1,那么如何将我的
对象集
转换回DbSet< T>
所以我可以执行我的查询?如果我设置了一个断点和检查,我可以看到我所有的数据只是坐在那里。
注意是EF7
其他信息:
-
requestedTable
是完全限定类型EG:< mysystem> .Models.Shared.Users
/ li>
EDIT(2016/5/5)
我最终只是用简单的SQL来做这些 - 如果有人设法得到这个工作,请让我知道!
通过使用通用方法并使用 DbContext.Set< TEntity>()
,这将更简单。您可以在运行时创建一个通用的方法:
public IActionResult GetTableData(string requestedContext,string requestedTable)
{
var context = GetContext(requestedContext);
if(context == null)
{
return new ErrorObjectResult(Invalid context specified);
}
var entity = context.GetEntity(requestedTable);
if(entity == null)
{
return new ErrorObjectResult(Invalid table specified);
}
var boundMethod = s_getTableDataMethodInfo.MakeGenericMethod(entity.ClrType);
return boundMethod.Invoke(this,new object [] {context})as IActionResult;
}
private static readonly MethodInfo s_getTableDataMethodInfo
= typeof(MyController).GetTypeInfo()。GetDeclaredMethod(GetTableDataForEntity);
private IActionResult GetTableDataForEntity< TEntity>(DbContext context)
其中TEntity:class
{
var data = Request.Query;
var start = Convert.ToInt32(data [start]。ToString());
var count = Convert.ToInt32(data [length]。ToString());
var search = data [search [value]];
返回新的ObjectResult(context.Set< TEntity>()。Skip(start).Take(count));
}
I am attempting to make a generic table viewer/editor for an MVC 6 application.
I currently use
Context.GetEntityTypes();
To return me a list of tables.
Now I need to fetch the data for a specific type. My current implementation is:
// On my context
public IQueryable<dynamic> GetDbSetByType(string fullname)
{
Type targetType = Type.GetType(fullname);
var model = GetType()
.GetRuntimeProperties()
.Where(o =>
o.PropertyType.IsGenericType &&
o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
o.PropertyType.GenericTypeArguments.Contains(targetType))
.FirstOrDefault();
if (null != model)
{
return (IQueryable<dynamic>)model.GetValue(this);
}
return null;
}
With this code in my controller
[HttpGet("{requestedContext}/{requestedTable}/data")]
public IActionResult GetTableData(string requestedContext, string requestedTable)
{
var data = Request.Query;
var context = GetContext(requestedContext);
if (context == null)
{
return new ErrorObjectResult("Invalid context specified");
}
var entity = context.GetEntity(requestedTable);
if (entity == null)
{
return new ErrorObjectResult("Invalid table specified");
}
var set = context.GetDbSetByType(entity.ClrType.AssemblyQualifiedName);
if (set == null)
{
return new ErrorObjectResult("Invalid table specified - DbSet could not be found");
}
var start = Convert.ToInt32(data["start"].ToString());
var count = Convert.ToInt32(data["length"].ToString());
var search = data["search[value]"];
return new ObjectResult(set.Skip(start).Take(count));
}
As it is, this will return the data of length count
and from position start
. However I cannot perform queries on the specific properties of the IQueryable<dynamic>
.
The problem is:
- This seems like a trivial thing to do, so I am almost sure I am missing something - this must be easy to do.
- If not 1, then how would I convert my
object set
back to aDbSet<T>
so I can perform my queries? If I set a breakpoint and inspect I can see all my data just sitting there.
NOTE: This is EF7
ADDITIONAL INFO:
- The
requestedTable
is the fully qualified type EG:<mysystem>.Models.Shared.Users
EDIT (2016/5/5)
I ended up just doing it all in plain SQL - if anyone does manage to get this working please let me know!
This would be simpler by using a generic method and using DbContext.Set<TEntity>()
. You can create a generic method at runtime like this:
public IActionResult GetTableData(string requestedContext, string requestedTable)
{
var context = GetContext(requestedContext);
if (context == null)
{
return new ErrorObjectResult("Invalid context specified");
}
var entity = context.GetEntity(requestedTable);
if (entity == null)
{
return new ErrorObjectResult("Invalid table specified");
}
var boundMethod = s_getTableDataMethodInfo.MakeGenericMethod(entity.ClrType);
return boundMethod.Invoke(this, new object[] { context }) as IActionResult;
}
private static readonly MethodInfo s_getTableDataMethodInfo
= typeof(MyController).GetTypeInfo().GetDeclaredMethod("GetTableDataForEntity");
private IActionResult GetTableDataForEntity<TEntity>(DbContext context)
where TEntity : class
{
var data = Request.Query;
var start = Convert.ToInt32(data["start"].ToString());
var count = Convert.ToInt32(data["length"].ToString());
var search = data["search[value]"];
return new ObjectResult(context.Set<TEntity>().Skip(start).Take(count));
}
这篇关于从类型获取DbSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!