我已经为我的一些实体类实现了一个接口:
public partial class Order : IReportable
{
public string TableName { get { return "Order"; } }
}
public partial class Client: IReportable
{
public string TableName { get { return "Client"; } }
}
public interface IReportable
{
string TableName { get; }
}
然后我将其添加到DbContext:
public virtual DbSet<IReportable> IReportable { get; set; }
当我尝试查询实现此接口的所有表时(如此处所示):
var result = from reportabletable in db.IReportable
where reportabletable.TableName == table_name
select reportabletable
我得到以下异常:
类型&#39; Report.DataAccess.IReportable&#39;没有映射。检查一下 尚未使用Ignore方法明确排除该类型 或NotMappedAttribute数据注释。验证类型是否 定义为类,不是原始的或通用的,并且不继承 来自EntityObject。
答案 0 :(得分:6)
我会选择这样的事情:
创建此扩展方法
public static class DbContextExtensions
{
public static IEnumerable<T> SetOf<T>(this DbContext dbContext) where T : class
{
return dbContext.GetType().Assembly.GetTypes()
.Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface)
.SelectMany(t => Enumerable.Cast<T>(dbContext.Set(t)));
}
}
并像这样使用它:
using (var db = new dbEntities())
{
var result = from reportabletable in db.SetOf<IReportable>()
where reportabletable.TableName == table_name
select reportabletable
}
答案 1 :(得分:2)
EF并不喜欢将接口直接映射到表。您可以通过使用通用存储库来解决这个问题,如Here!
所述然后使用存储库方法并提供要查询的表的类型。类似于:myRepo.GetAll<myClient.GetType()>();
获取继承该接口的类并运行所有这些接口的查询:
var types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)));
foreach (var mytype in types)
{ // aggregate query results }
希望这有帮助!可能有更优雅的解决方案
答案 2 :(得分:1)
首先,MarcGravell评论的是钱。由您决定要查询哪个表。 我个人查看实现接口或具有自定义属性的poco类型列表。但是,如果您只想通过DBContext,那么这里有一些扩展可以让您访问“名称”。您仍然需要一次一个地访问该部分上下文。
你可以通过泛型来做到这一点,但你可以直接按照你的建议去做 您需要迭代一个类型列表。 例如:
ReportRespository:BaseRespository,其中t:IReport
检查程序集中的某些类型和属性 例如
/// <summary>
/// POCOs that have XYZ Attribute of Type and NOT abstract and not complex
/// </summary>
/// <returns></returns>
public static List<Type> GetBosDirDBPocoList() {
var result = new List<Type>();
// so get all the Class from teh assembly that public non abstract and not complex
foreach (var t in Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType != null
&& t.IsClass
&& t.IsPublic
&& !t.IsAbstract
&& !t.IsComplexType()
&& t.GetMyAttribute() != null)) {
result.Add(t);
}
}
return result;
}
public static GetMyAttribute(this Type T) {
var myAttr= T.GetCustomAttributes(true)
.Where(attribute => attribute.GetType()
.Name == "XYZAttr").Cast<BosDir>().FirstOrDefault();
return myAttr;
}
<强>扩展强>
public static class DalExtensions {
// DbSet Names is the plural property name in the context
public static List<string> GetModelNames(this DbContext context) {
var propList = context.GetType().GetProperties();
return GetDbSetNames(propList);
}
// DbSet Names is the plural property name in the context
public static List<string> GetDbSetTypeNames<T>() where T : DbContext {
var propList = typeof (T).GetProperties();
return GetDbSetNames(propList);
}
// DBSet Types is the Generic Types POCO name used for a DBSet
public static List<string> GetModelTypes(this DbContext context) {
var propList = context.GetType().GetProperties();
return GetDbSetTypes(propList);
}
// DBSet Types POCO types as IEnumerable List
public static IEnumerable<Type> GetDbSetPropertyList<T>() where T : DbContext {
return typeof (T).GetProperties().Where(p => p.PropertyType.GetTypeInfo()
.Name.StartsWith("DbSet"))
.Select(propertyInfo => propertyInfo.PropertyType.GetGenericArguments()[0]).ToList();
}
// DBSet Types is the Generic Types POCO name used for a DBSet
public static List<string> GetDbSetTypes<T>() where T : DbContext {
var propList = typeof (T).GetProperties();
return GetDbSetTypes(propList);
}
private static List<string> GetDbSetTypes(IEnumerable<PropertyInfo> propList) {
var modelTypeNames = propList.Where(p => p.PropertyType.GetTypeInfo().Name.StartsWith("DbSet"))
.Select(p => p.PropertyType.GenericTypeArguments[0].Name)
.ToList();
return modelTypeNames;
}
private static List<string> GetDbSetNames(IEnumerable<PropertyInfo> propList) {
var modelNames = propList.Where(p => p.PropertyType.GetTypeInfo().Name.StartsWith("DbSet"))
.Select(p => p.Name)
.ToList();
return modelNames;
}
}
}
答案 3 :(得分:0)
接受的解决方案在EF Core中不起作用。 这是我的第一个工作草案
public IEnumerable<T> SetOf<T>() where T : class
{
var firstType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
.FirstOrDefault(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface);
if (firstType == null) return new List<T>();
var dbSetMethodInfo = typeof(DbContext).GetMethod("Set");
var dbSet = dbSetMethodInfo.MakeGenericMethod(firstType);
IQueryable<T> queryable = ((IQueryable)dbSet.Invoke(this, null)).Cast<T>();
return queryable.ToList().Cast<T>();
}
那么您可以像这样使用
_dbContext.SetOf<ISomeInterface>();