我需要一个像这样的通用查询但在网络上找不到任何东西(可能是因为搜索不好!)
int[] ids = new int[]{1,2,3}
var q = context.where(o=> ids.contains(o.id));
我的实体类型未知,但我确定:
int
所以签名是这样的:
Public IQueryable<T> GetRecords(int[] keys)
{
var dbset = context.Set<T>();
...//the generic query
}
在通用和非通用实现中,同样的SQL输出(具有相同的性能)也很重要。
答案 0 :(得分:1)
您可以使用多态来解决您的问题。 Crete是一个声明整数Id
属性并在您的实体中实现的接口,因为它对所有这些属性都是通用的。然后对泛型参数T
进行约束,强制它成为实现接口的类型,因此编译器将知道T
将是具有Id
属性的类型,你将能够访问它:
// IId is the interface that should be implemented
public IQueryable<T> GetRecords<T>(int[] keys) where T : IId
{
var dbset = context.Set<T>();
...//the generic query
}
答案 1 :(得分:1)
private IDictionary<Type, string> _primaryKeyCache = new Dictionary<Type, string>();
public IQueryable<T> GetRecords(int[] keys)
{
var dbSet = context.Set<T>();
var type = typeof(T);
string primaryKeyName;
if(!_primaryKeyCache.TryGetValue(type, out primaryKeyName)){
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var set = objectContext.CreateObjectSet<YourEntity>();
var keyName = set.EntitySet.ElementType
.KeyMembers
.Select(k => k.Name)
.First();
_primaryKeyCache[type] = primaryKeyName = keyName;
}
return dbSet.DynamicContains<T, int>(primaryKeyName, keys);
}
private static IQueryable<T> DynamicContains<T, TProperty>(
this IQueryable<T> query,
string property,
IEnumerable<TProperty> items)
{
var pe = Expression.Parameter(typeof(T));
var me = Expression.Property(pe, property);
var ce = Expression.Constant(items);
var call = Expression.Call(typeof(Enumerable), "Contains", new[] { me.Type }, ce, me);
var lambda = Expression.Lambda<Func<T, bool>>(call, pe);
return query.Where(lambda);
}
那应该做你需要的。
答案 2 :(得分:0)
创建一个新界面,例如IKeyedByIntEntity
public interface IKeyedByIntEntity
{
int Key { get; }
}
让查询中使用的所有实体都实现该接口。在理想的世界中,该字段具有相同的名称,因此您可以将其用作界面中的属性名称,因此无需更改实体的实现。
public class MyEntity : IKeyedByIntEntity
{
public int Key { get; set; }
public string Value { get; set; }
}
更新您的GetRecords函数或类以要求接口,例如其中一个......
public class Fetch
{
public IQueryable<T> GetRecords<T>(int[] keys)
where T : IKeyedByIntEntity
{
IQueryable<T> records = this.context.Where(e => keys.Contains(e.Key));
return records;
}
}
public class Fetch<T> where T : IKeyedByIntEntity
{
public IQueryable<T> GetRecords(int[] keys)
{
IQueryable<T> records = this.context.Where(e => keys.Contains(e.Key));
return records;
}
}