C# 如何按主键或任何默认值进行排序,以允许跳过并接受泛型集合上的EF?
我有一个方法,它采用了C# 如何按主键或任何默认值进行排序,以允许跳过并接受泛型集合上的EF?,c#,reflection,entity-framework-6,C#,Reflection,Entity Framework 6,我有一个方法,它采用了IQueryable,我在它上面做了一些通用的东西。通常会指定order属性,这很好,但有时没有提供任何内容,我需要通过某种方式对其进行排序,以便应用skip/take 我会很高兴在主键上这样做,但任何能起作用的东西都是好的 但我似乎无法从IQueryable集合中获取主键。我尝试了一些我在网上找到的代码来循环使用PropertyInfo[]properties=typeof(T).GetProperties()属性和GetCustomAttributes()但是似乎根本没
IQueryable
,我在它上面做了一些通用的东西。通常会指定order属性,这很好,但有时没有提供任何内容,我需要通过某种方式对其进行排序,以便应用skip/take
我会很高兴在主键上这样做,但任何能起作用的东西都是好的
但我似乎无法从IQueryable
集合中获取主键。我尝试了一些我在网上找到的代码来循环使用PropertyInfo[]properties=typeof(T).GetProperties()代码>属性和GetCustomAttributes()
但是似乎根本没有任何属性
我正在使用此方法,但它只给了我null
:
private PropertyInfo GetPrimaryKeyInfo<T>()
{
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo pI in properties)
{
System.Object[] attributes = pI.GetCustomAttributes(true);
foreach (object attribute in attributes)
{
if (attribute is EdmScalarPropertyAttribute)
{
if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty == true)
return pI;
}
else if (attribute is System.Data.Linq.Mapping.ColumnAttribute)
{
if ((attribute as System.Data.Linq.Mapping.ColumnAttribute).IsPrimaryKey == true)
return pI;
}
}
}
return null;
}
私有属性信息GetPrimaryKeyInfo()
{
PropertyInfo[]properties=typeof(T).GetProperties();
foreach(PropertyInfo pI in properties)
{
System.Object[]attributes=pI.GetCustomAttributes(true);
foreach(属性中的对象属性)
{
if(属性为EdmScalarPropertyAttribute)
{
if((属性为EdmScalarPropertyAttribute).EntityKeyProperty==true)
返回pI;
}
else if(属性为System.Data.Linq.Mapping.ColumnAttribute)
{
if((属性为System.Data.Linq.Mapping.ColumnAttribute).IsPrimaryKey==true)
返回pI;
}
}
}
返回null;
}
我可以在我的实体模型中看到,对于我正在使用的T实例,有一个主键集
有人能提供建议吗?您可以从EF元数据(不是很直观)中获得这些信息。例如,以下内容将返回PK属性名称,然后您可以简单地使用反射或
Expression.property
生成必要的访问器/表达式:
static IEnumerable<string> GetPrimaryKeyNames<TEntity>(DbContext dbContext)
where TEntity : class
{
var entityType = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)dbContext).ObjectContext
.CreateObjectSet<TEntity>().EntitySet.ElementType;
return entityType.KeyProperties.Select(p => p.Name);
}
静态IEnumerable GetPrimaryKeyNames(DbContext DbContext)
地点:班级
{
var entityType=((System.Data.Entity.Infrastructure.IOObjectContextAdapter)dbContext).ObjectContext
.CreateObjectSet().EntitySet.ElementType;
返回entityType.KeyProperties.Select(p=>p.Name);
}
您可以扩展域模型,为所有实体添加一个接口,而不是使用反射,这样可以帮助您使用通用代码,例如:
public interface IEntity
{
int Id { get; set; }
}
然后您可以编写一些通用方法,如:
public void Update<T>(IQueryable<T> query, Expression<Func<T, object>> orderBy = null)
where T : IEntity
{
if (orderBy == null)
query = query.OrderBy(m => m.Id);
else
query = query.OrderBy(orderBy);
}
公共无效更新(IQueryable查询,表达式orderBy=null)
其中T:
{
if(orderBy==null)
query=query.OrderBy(m=>m.Id);
其他的
query=query.OrderBy(OrderBy);
}
此解决方案取决于实体的外观、它们具有何种不同的键以及是否可以将它们统一到一个或多个接口。EF6抱歉-我已更新了标记问题在于我无法访问此方法中的上下文,我只有一个
IQueryable
。然后您需要以某种方式将该信息传递给该方法。或者使用我的答案中的(有点黑)方法。您知道如何将参数传递给该方法,例如类似于()=>myEntity.EntityId的内容,以便我可以使用它吗?如何指定该方法的order属性?可能是表达式或字符串?我想无论您对sort属性使用了什么,您都可以将其用于此目的。我现在正在执行collection.OrderByDescending(Expression.Lambda(sortSelectorParameter))
(对于字符串提供的排序),但是如果我可以传入c=>c.CustomerId
,那么最好使用强类型。。。我想我只是通过了一个Func
然后?但我不知道那是什么。