实体框架按主键过滤

2023-12-06

我正在编写一个通用的 CRUD 服务,我正在尝试实现Get方法与可选的虚拟方法来包含属性但是我遇到了一些麻烦,因为FindAsync仅在 a 上声明DbSet:

public async virtual Task<TDTO> Get(object[] id)
{
     // I want to do something like this
     var entity = await this.ApplyGetIncludes(this.GetEntityDBSet()).FindAsync(id)
     return this.AdaptToDTO(entity);
}

protected virtual DbSet<TEntity> GetEntityDBSet()
{
    return this._context.Set<TEntity>();
}

protected virtual IQueryable<TEntity> ApplyGetIncludes(IQueryable<TEntity> queryable)
{
    return queryable;
}

我想做这样的事情,如上图所示:

var entity = await this.ApplyGetIncludes(this.GetEntityDBSet()).FindAsync(id)

但我知道这行不通,因为我们需要数据库集,所以我会设置做这样的事情:

var entity = await this.ApplyGetIncludes(this.GetEntityDBSet().FilterByPK(id))
                      .FirstOrDefaultAsync();

有谁知道我如何通过主键过滤DbSet?


这是可能的,但该方法需要访问DbContext为了获取描述主键的元数据。然后,它可以根据该元数据和传递的值动态构建谓词 lambda 表达式。

首先,我们需要一个收集有关实体主键属性信息的方法。

对于 EF Core 来说很简单:

static IReadOnlyList<IProperty> GetPrimaryKeyProperties(DbContext dbContext, Type clrEntityType)
{
    return dbContext.Model.FindEntityType(clrEntityType).FindPrimaryKey().Properties;
}

对于 EF6,它有点复杂,但仍然可行:

struct KeyPropertyInfo
{
    public string Name;
    public Type ClrType;
}

public static IReadOnlyList<KeyPropertyInfo> GetPrimaryKeyProperties(DbContext dbContext, Type clrEntityType)
{
    var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
    var metadata = objectContext.MetadataWorkspace;
    var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
    var entityType = metadata.GetItems<EntityType>(DataSpace.OSpace)
        .Single(e => objectItemCollection.GetClrType(e) == clrEntityType);
    return entityType.KeyProperties
        .Select(p => new KeyPropertyInfo
        {
            Name = p.Name,
            ClrType = p.PrimitiveType.ClrEquivalentType
        })
        .ToList();
}

现在构建谓词的方法是这样的:

static Expression<Func<T, bool>> BuildKeyPredicate<T>(DbContext dbContext, object[] id)
{
    var keyProperties = GetPrimaryKeyProperties(dbContext, typeof(T));
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = keyProperties
        // e => e.PK[i] == id[i]
        .Select((p, i) => Expression.Equal(
            Expression.Property(parameter, p.Name),
            Expression.Convert(
                Expression.PropertyOrField(Expression.Constant(new { id = id[i] }), "id"),
                p.ClrType)))
        .Aggregate(Expression.AndAlso);
    return Expression.Lambda<Func<T, bool>>(body, parameter);
}

这里棘手的部分是如何让 EF 使用参数化查询。如果我们简单地使用Expression.Constant(id[i]),生成的 SQL 将使用常量值而不是参数。因此,技巧是使用保存值的​​临时匿名类型常量表达式的成员访问表达式(即属性或字段)(基本上模拟闭包)。

从上述方法获得谓词后,您可以将其用于FirstOrDefaultAsync或任何其他过滤方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实体框架按主键过滤 的相关文章

随机推荐

  • 释放数据库中库存的最佳实践

    我正在构建一个售票应用程序 用于跟踪门票库存 并在特定门票售完时停用它们 我想知道当订单中途放弃时将库存释放回商店的最佳做法是什么 目前的流量 用户添加items to an order as line items和order付款成功后标记
  • 如何动态添加edittext到android

    我想将 edittext 动态添加到 android 显示 我想做一些类似于 Android 联系人的东西 您可以在其中动态添加字段并在不需要时删除它们 感谢您的帮助 动态查看一切 TextView tv new TextView this
  • printf 中 double 的正确格式说明符

    正确的格式说明符是什么double在 printf 中 是吗 f或者是 lf 我相信这是 f 但我不确定 代码示例 include
  • 如何将nif流文件从1.12版本迁移到1.16.3

    我有一个在 NiFi 1 12 0 中运行的数据流 此安装的相关属性如下 nifi sensitive props key nifi sensitive props key protected nifi sensitive props al
  • .net实体框架与oracle 11g

    我正在将实体框架与 Oracle 提供程序 Oracle ManagedDataAccessDTC 一起使用 从 Visual Studio 运行一切正常 但是当我将其发布到 IIS 时 我收到连接错误异常 这是我的 webconfig 女
  • 使用 dplyr 从数据帧中采样子组行

    如果我想从不同组中随机选择一些样本 我使用 plyr 包和下面的代码 require plyr sampleGroup lt function df size df sample nrow df size size iris sample
  • 跟踪 Android 应用程序内的用户空闲时间

    据我所知 没有系统API可供我获取用户空闲时间 当我说用户空闲时间时 我的意思是用户在我的应用程序内的触摸屏上进行一些交互 因此 我想自己跟踪它 我想到的方法是扩展Activity并覆盖onuserinteraction方法来保存最后用户活
  • 图像上传后,React Native 中仅 iOS 的图像 uri 为空

    在我的 React Native 应用程序中 我添加了上传多个图像的功能 这些图像将存储为 image 包括 uri 这对于 Android 来说非常有效 但对于iOS来说 创建的image 也包含一些数据 但与android完全不同 对于
  • 从“.exe”中删除调试信息[重复]

    这个问题在这里已经有答案了 如果我将 C 程序 exe 放入文本编辑器中 我可以在其中找到调试信息 我怎样才能删除它 编辑 我不关心 pdb 文件 我只关心可执行文件中有 pdb 文件的路径 该路径包含我的名字 在本例中是巧合 我的问题是如
  • 如何在.NET Core 3.1中的Newtonsoft JsonConverter中注入依赖

    我无法让依赖注入在 NET Core 3 1 中为以下 Newtonsoft JsonConverter 工作 我只想在属性级别使用它 而不是在全局级别使用它 因此 只有当指定的属性来自某个类时才应执行 JsonConverter publ
  • 如何通过 SQL 将计算列添加到 Access

    如何在 SQL 中向 Access 表添加计算列 我知道我可以使用 SQL 添加一列 如下所示 ALTER TABLE Clients ADD COLUMN AccountDate TEXT 60 谢谢 维托尔 您无法使用 SQL 添加计算
  • Jackson 的 JsonIgnore

    JsonIgnore 注释似乎对我不起作用 有什么想法吗 public class JsonTest implements Serializable JsonIgnore private static JsonTest instance n
  • 在最新的 64 位 Intel CPU 上,如何在没有隐式锁的情况下与寄存器交换堆栈顶部?

    x64 调用约定使用寄存器最多前 4 个参数 rcx rdx r8 r9 并将其余参数传递到堆栈上 在这种情况下 处理补充参数的明显方法是asm程序如下 procedure example param1 rcx param2 rdx par
  • 使用 ItextSharp 验证数字签名

    我正在尝试使用 iTextSharp 验证 C 中的数字签名 我按照 iText 网络中的示例进行操作 http gitlab itextsupport com itextsharp tutorial blob master signatu
  • iPhone 使用 NSURLConnection 发送 POST

    我在使用 NSURLConnection 将 POST 数据发送到 PHP 脚本时遇到一些问题 这是我的代码 const char bytes NSString stringWithFormat n
  • 两个表之间最近点的唯一分配

    In my Postgres 9 5数据库与邮政地理信息系统2 2 0安装后 我有两个带有几何数据 点 的表 我想将一个表中的点分配给另一个表中的点 但我不想要buildings gid被分配两次 只要一buildings gid已分配 不
  • 颤动中的自定义 Sliver 应用栏,其中一个图像和 2 个文本小部件在滚动时进入应用栏

    我想实现条子应用程序栏 如下面的两张图片所示 经过多次谷歌搜索后 我发现了CustomScrollView小部件和SliverAppBar但是所有关于条子应用程序栏的在线教程和博客都显示了一个简单的小部件 其中图像消失在应用程序栏中 并在滚
  • 从 IPython Notebook 中的日志记录模块获取输出

    当我在 IPython Notebook 中运行以下命令时 我没有看到任何输出 import logging logging basicConfig level logging DEBUG logging debug test 有人知道如何
  • php从字符串调用数组

    我有一个包含数组元素的字符串 str some string array array 我怎样才能得到的值 array some string using str 这适用于任意数量的键 keys explode substr str 1 1
  • 实体框架按主键过滤

    我正在编写一个通用的 CRUD 服务 我正在尝试实现Get方法与可选的虚拟方法来包含属性但是我遇到了一些麻烦 因为FindAsync仅在 a 上声明DbSet public async virtual Task