如何找到Id
中最大的DbSet.Set<T>()
?
注意:不是 DbSet<TEntity>
。
我不知道运行时的类型。
上下文:我有20个表/实体,我正在使用 泛型 方法进行处理。
该过程涉及查找该表/实体的最大ID并将其与手头的记录进行比较。
如果记录的id
大于数据库,那么它将被插入到数据库中。
到目前为止,我尝试过使用反射:
DbSet<T> table = DbContext.Set<T>();
var lastRecord = table.LastOrDefault(); // throws not supported error
var idProperty = lastRecord.GetType().GetProperties()
.FirstOrDefault(p => p.Name.Equals("Id");
int maxId = (int)idProperty.GetValue(lastRecord);
我也尝试过使用界面演员:
interface ICommonEntity
{ // this interface allows the generic method
string StringId { get;} // to know how to handle entity Id's of
int? IntId { get; } // different types (string vs int).
}
var whatever = table.OrderByDescending(e => (e as ICommonEntity).IntId).FirstOrDefault();
int maxId = (whatever as ICommonEntity).IntId ?? 0;
但是上面会产生以下 错误 :
不支持输入类型为xx的'TypeAs'表达式。并检查yy类型。 LINQ to Entities查询中仅支持实体类型和复杂类型
其他数据:我的所有实体都拥有Id
类型的列/属性int
。
我已经完成的网络搜索主要指向类型已知的解决方案,例如TEntity
,db.Users.xxx()等。
在回复Ian's answer时,我无法直接使用Id
。的为什么?
我的一个实体有一个名为Id
的字段,但类型为string
。
class EntityStringId : ICommonEntity
{
public string Id { get; set; }
public string StringId => Id;
public int? IntId => null;
}
class EntityIntId : ICommonEntity
{
public int Id { get; set; }
public string StringId => null;
public int? IntId => Id;
}
如果我尝试使用IntId
进行排序,
private void SomeMethod<T>(string file)
//where T : class // original
//where T : ICommonEntity // cannot. DbContext.Set<T>(); requires class
where T : class, ICommonEntity // throws exception
{
var table_T = DbContext.Set<T>();
var maxId = table_T.Max(e => e.IntId); // throws exception ↓
}
LINQ to Entities不支持指定的类型成员'IntId'。 仅支持初始化程序,实体成员和实体导航属性。
为了更好的画面,我方法的逻辑:
private void ProcessCsvToDb<T>(
DbSet<T> table,
T csvRecord) where T : class
{
var iRecord = csvRecord as ICommonEntity;
T dbRecord = null;
if (!string.IsNullOrEmpty(iRecord.StringId))
{
dbRecord = table.Find(iRecord.StringId);
}
else if (iRecord.IntId != null)
{
dbRecord = table.Find(iRecord.IntId);
}
}
答案 0 :(得分:4)
为了在没有基类/接口的情况下执行此操作,您需要手动编写表达式:
public static IOrderedQueryable<int> OrderById(Type entityType)
{
var dbSet = context.Set(entityType);
var item = Expression.Parameter(entityType, "item");
var property = Expression.Property(item, "Id");
var lambda = Expression.Lambda<Func<T, int>>(property, item);
// the above generates:
// item => item.Id
return dbSet.OrderByDescending(lambda);
}
答案 1 :(得分:1)
您可以构建表达式以按ID排序,但DynamicQueryable class会为您执行此操作:
DbSet<T> table = assignFromSomeWhere();
var maxId = table.OrderBy("Id desc").FirstOrDefault();
DynamicQueryable
还为您提供了不同的扩展方法(动态Where,Select)。显然,自己构建表达式会有更大的满足感,但有时它非常复杂,而且这个库有很多帮助。
答案 2 :(得分:0)
如果你有一个界面,正如评论中所讨论的那样,你有什么理由不能这样做以避免演员:
public static int? GetMaxId<T>(DBSet<T> dbSet)
where T : ICommonEntity
{
return dbSet.OrderByDescending(e => e.Id).FirstOrDefault();
}