Entity framework 非泛型属性中的实体框架泛型查询
在实体框架中,我有如下对象集Entity framework 非泛型属性中的实体框架泛型查询,entity-framework,generics,Entity Framework,Generics,在实体框架中,我有如下对象集 public partial class Building { public int BuildingID { get; set; } public string BuildingName { get; set; } } public partial class Town { public int TownID { get; set; } public string TownName { get; set;
public partial class Building
{
public int BuildingID { get; set; }
public string BuildingName { get; set; }
}
public partial class Town
{
public int TownID { get; set; }
public string TownName { get; set; }
}
我想创建一个通用查询,如
T.OrderBy(o=>o.Id).Skip(maxDispItem * (page - 1)).Take(maxDispItem).ToList();
T是泛型类,可以是Building或Town,但问题是
BuildingId
和TownId
具有不同的名称。我不想将它们的名称更改为Id
并创建接口IIdentity
也许你可以试试这样:
var query = (typeof(T) == typeof(Building) ?
context.Buildings.Select(b => new { Id = b.BuildingId, Name = b.BuildingName }) :
context.Towns.Select(t => new { Id = t.TownId, Name = b.TownName }))
.OrderBy(o => o.Id)...
未测试,但值得测试…您可以创建一个通用方法,该方法查找用KeyAttribute修饰的字段,然后按找到的键字段执行排序。我已经测试过你的模型,效果很好。看看代码片段 DbContext:
using System.Collections.Generic;
using System.Data.Entity;
namespace ConsoleApplication28.Entities
{
public class AppDbContext : DbContext
{
public AppDbContext()
{
Database.Connection.ConnectionString = @"Data Source=NOTEBOOK-PC;Initial Catalog=StackOverflowTest;Integrated Security=True";
Database.SetInitializer(new AppDbInitializer());
}
public DbSet<Town> Towns { get; set; }
public DbSet<Building> Buildings { get; set; }
}
public class AppDbInitializer : DropCreateDatabaseIfModelChanges<AppDbContext>
{
protected override void Seed(AppDbContext context)
{
context.Buildings.AddRange(new List<Building>
{
new Building {BuildingName = "Building1"},
new Building {BuildingName = "Building2"},
});
context.Towns.AddRange(new List<Town>
{
new Town {TownName = "Town1"},
new Town {TownName = "Town2"},
});
context.SaveChanges();
base.Seed(context);
}
}
}
城镇
using System.ComponentModel.DataAnnotations;
namespace ConsoleApplication28.Entities
{
public class Town
{
[Key]
public int TownID { get; set; }
public string TownName { get; set; }
}
}
节目
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using ConsoleApplication28.Entities;
using System.ComponentModel.DataAnnotations;
namespace ConsoleApplication28
{
class Program
{
static void Main(string[] args)
{
const int maxDispItem = 10;
const int page = 1;
var db = new AppDbContext();
var towns = db.Towns.OrderByKey().Skip(maxDispItem * (page - 1)).Take(maxDispItem).ToList();
var buildings = db.Buildings.OrderByKey().Skip(maxDispItem * (page - 1)).Take(maxDispItem).ToList();
}
}
public static class Extensions
{
/// <summary>
/// Sorts the elements of a sequence in ascending order according to a key specified using KeyAttribute
/// </summary>
public static IOrderedQueryable<T> OrderByKey<T>(this IQueryable<T> source, bool isAsc = true)
{
var type = typeof(T);
var keyProperty = type.GetProperties().Single(x => x.GetCustomAttributes(typeof(KeyAttribute)).Any());
return source.OrderBy(keyProperty.Name, isAsc);
}
#region COPIED FROM THERE http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property, bool isAsc)
{
return isAsc ? source.OrderBy(property) : source.OrderByDescending(property);
}
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderBy");
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderByDescending");
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenBy");
}
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenByDescending");
}
static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach (string prop in props)
{
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<T>)result;
}
#endregion
}
}
使用系统;
使用System.Linq;
使用System.Linq.Expressions;
运用系统反思;
使用ConsoleApplication28.实体;
使用System.ComponentModel.DataAnnotations;
命名空间控制台应用程序28
{
班级计划
{
静态void Main(字符串[]参数)
{
const int maxDispItem=10;
const int page=1;
var db=新的AppDbContext();
var towns=db.towns.OrderByKey();
var buildings=db.buildings.OrderByKey().Skip(maxDispItem*(第1页)).Take(maxDispItem).ToList();
}
}
公共静态类扩展
{
///
///根据使用KeyAttribute指定的键,按升序对序列的元素进行排序
///
公共静态IOrderedQueryable OrderByKey(此IQueryable源,bool isAsc=true)
{
var类型=类型(T);
var keyProperty=type.GetProperties().Single(x=>x.GetCustomAttributes(typeof(KeyAttribute)).Any());
返回source.OrderBy(keyProperty.Name,isAsc);
}
#从那里复制的区域http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet
公共静态IOrderedQueryable OrderBy(此IQueryable源,字符串属性,bool isAsc)
{
返回isAsc?source.OrderBy(属性):source.OrderByDescending(属性);
}
公共静态IOrderedQueryable OrderBy(此IQueryable源,字符串属性)
{
返回ApplyOrder(来源、属性、“订购者”);
}
公共静态IOrderedQueryable OrderByDescending(此IQueryable源,字符串属性)
{
返回ApplyOrder(源,属性,“OrderByDescending”);
}
公共静态IOrderedQueryable ThenBy(此IOrderedQueryable源,字符串属性)
{
返回申请者(来源、财产,“ThenBy”);
}
公共静态IOrderedQueryable然后按降序(此IOrderedQueryable源,字符串属性)
{
返回ApplyOrder(源、属性,“然后按降序”);
}
静态IOrderedQueryable ApplyOrder(IQueryable源、字符串属性、字符串方法名)
{
字符串[]props=property.Split('.');
类型=类型(T);
ParameterExpression arg=Expression.Parameter(类型为“x”);
表达式expr=arg;
foreach(道具中的字符串道具)
{
PropertyInfo pi=type.GetProperty(prop);
expr=Expression.Property(expr,pi);
type=pi.PropertyType;
}
Type delegateType=typeof(Func)。MakeGenericType(typeof(T),Type);
LambdaExpression lambda=Expression.lambda(delegateType,expr,arg);
对象结果=typeof(Queryable).GetMethods().Single(
method=>method.Name==methodName
&&方法.IsGenericMethodDefinition
&&方法。GetGenericArguments()。长度==2
&&方法。GetParameters().Length==2)
.MakeGenericMethod(typeof(T),type)
.Invoke(null,新对象[]{source,lambda});
返回(IOrderedQueryable)结果;
}
#端区
}
}
如果无法创建接口,则唯一的其他选项是建筑和城镇继承自的基类。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using ConsoleApplication28.Entities;
using System.ComponentModel.DataAnnotations;
namespace ConsoleApplication28
{
class Program
{
static void Main(string[] args)
{
const int maxDispItem = 10;
const int page = 1;
var db = new AppDbContext();
var towns = db.Towns.OrderByKey().Skip(maxDispItem * (page - 1)).Take(maxDispItem).ToList();
var buildings = db.Buildings.OrderByKey().Skip(maxDispItem * (page - 1)).Take(maxDispItem).ToList();
}
}
public static class Extensions
{
/// <summary>
/// Sorts the elements of a sequence in ascending order according to a key specified using KeyAttribute
/// </summary>
public static IOrderedQueryable<T> OrderByKey<T>(this IQueryable<T> source, bool isAsc = true)
{
var type = typeof(T);
var keyProperty = type.GetProperties().Single(x => x.GetCustomAttributes(typeof(KeyAttribute)).Any());
return source.OrderBy(keyProperty.Name, isAsc);
}
#region COPIED FROM THERE http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property, bool isAsc)
{
return isAsc ? source.OrderBy(property) : source.OrderByDescending(property);
}
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderBy");
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "OrderByDescending");
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenBy");
}
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
{
return ApplyOrder<T>(source, property, "ThenByDescending");
}
static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach (string prop in props)
{
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable<T>)result;
}
#endregion
}
}