查找 DbSet<T> 的 Max(Id),其中 T 未知

3 c# linq generics entity-framework

如何找到Ida 中最大的一个DbSet.Set<T>()

\n\n

:不是DbSet<TEntity>

\n\n

我不知道运行时的类型。

\n\n

上下文:我有 20 个表/实体,我正在使用通用方法进行处理。

\n\n

该过程涉及查找该表/实体的最大 ID 并将其与手头的记录进行比较。

\n\n

如果记录id大于数据库,则将其插入数据库。

\n\n

到目前为止,我已经尝试使用反射:

\n\n
DbSet<T> table = DbContext.Set<T>();\nvar lastRecord = table.LastOrDefault();  // throws not supported error\nvar idProperty = lastRecord.GetType().GetProperties()\n                                     .FirstOrDefault(p => p.Name.Equals("Id");  \nint maxId = (int)idProperty.GetValue(lastRecord);\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还尝试过使用接口转换:

\n\n
interface ICommonEntity\n{                              // this interface allows the generic method\n    string StringId { get;}    // to know how to handle entity Id\'s of \n    int? IntId { get; }        // different types (string vs int).\n}                              \n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n
var whatever =  table.OrderByDescending(e => (e as ICommonEntity).IntId).FirstOrDefault();\nint maxId = (whatever as ICommonEntity).IntId ?? 0;\n
Run Code Online (Sandbox Code Playgroud)\n\n

但上面会产生以下错误

\n\n
\n

不支持输入类型为 xx 的“TypeAs”表达式。和 yy 类型的支票。LINQ to Entities 查询仅支持实体类型和复杂类型

\n
\n\n

附加数据:Id我的所有实体都有type 的列/属性int
\n我所做的网络搜索主要指向类型已知的解决方案,例如TEntitydb.Users.xxx() 等。\n


\n\n

更新

\n\n

针对Ian的 回答,我不能Id直接使用。为什么
\n我的一个实体有一个名为 的字段Id,但类型为string

\n\n
class EntityStringId : ICommonEntity\n{\n    public string Id { get; set; }\n    public string StringId => Id;\n    public int? IntId => null;\n}\n\nclass EntityIntId : ICommonEntity\n{\n    public int Id { get; set; }\n    public string StringId => null;\n    public int? IntId => Id;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我尝试使用它IntId来订购,

\n\n
private void SomeMethod<T>(string file)\n    //where T : class           // original\n    //where T : ICommonEntity   // cannot. DbContext.Set<T>(); requires class\n    where T : class, ICommonEntity  // throws exception\n    {\n        var table_T = DbContext.Set<T>();\n        var maxId = table_T.Max(e => e.IntId); // throws exception \xe2\x86\x93\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

LINQ to Entities 不支持指定的类型成员“IntId”。\n 仅支持初始值设定项、实体成员和实体导航属性。

\n
\n\n

为了获得更好的图片,我的方法的逻辑:

\n\n
private void ProcessCsvToDb<T>(\n        DbSet<T> table,\n        T csvRecord) where T : class\n{\n    var iRecord = csvRecord as ICommonEntity;\n    T dbRecord = null;\n    if (!string.IsNullOrEmpty(iRecord.StringId))\n    {\n        dbRecord = table.Find(iRecord.StringId);\n    }\n    else if (iRecord.IntId != null)\n    {\n        dbRecord = table.Find(iRecord.IntId);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

SO *_*ood 5

为了在没有基类/接口的情况下执行此操作,您需要手动编写表达式:

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);
}
Run Code Online (Sandbox Code Playgroud)