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

标签 c# entity-framework linq generics

如何找到最大的IdDbSet.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)转换:

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;

但是上面的代码会产生以下错误:

The 'TypeAs' expression with an input of type xx is not supported. and a check of type yy. Only entity types and complex types are supported in LINQ to Entities queries

其他数据:我的所有实体都有列/属性 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 ↓
    }

The specified type member 'IntId' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

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

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);
    }
}

最佳答案

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

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);
}

关于c# - 查找 DbSet<T> 的 Max(Id),其中 T 未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49842819/

相关文章:

c# - 如何确保我们的 .NET Core API 清理数据库连接?

linq - 使用 Linq 从 DataTable 单元格中修剪空格

c# - 在 C# 中加入两个条件

c# - 使用 nhibernate 和 mvc 进行分页

c# - EWS : Calendar Sharing Invitation and Extended Properties

c# - 在应用程序文件夹外读取单独的 web.config 文件

c# - Code First 类型 '' 上的属性 '' 上的ForeignKeyAttribute 无效。 Entity Framework

C#继承问题

c# - Entity Framework : Change connection string at runtime

c# - Linq 获取最后插入的 ID