首页 > 解决方案 > 使用 HasKey 查找实体而不显式指定查询中的所有键

问题描述

使用 EF,您可以指定一个复合键,HasKey所以我想有一种方法可以使用实体作为某些 API 的参数来在数据库中找到它,但我不知道如何。

我希望使用的FindAPI 需要一组键值,但我正在寻找的是这样的:

var setting = new Setting { Name = "WindowSize" };
setting = context.Find(setting);

由于我可以通过指定所有键,modelBuilder.Entity<Setting>.HasKey(s => new { s.Name })因此必须有一种方法可以重用它。你知道一个 API 或让它以这种方式工作的技巧吗?

Setting模型是可交换的,并且可能具有其他关键列。我希望能够自动找到它,而不必两次指定条件。

这意味着可以有:

modelBuilder.Entity<Setting>.HasKey(s => new { s.Name, s.Version })

我希望这个定义被重用于查询,而我不必说Find("name", "version")等等。但是context.SomeAPI(settingWithTwoKeys)

标签: c#entity-framework-core

解决方案


EF Core 中没有任何内置功能可以做到这一点,但编写一个.Find可以为您完成的扩展方法并不难。这是执行此操作的示例方法(未经测试)。

(注意:当您调用此方法时,您可以依赖通用参数推断,并且只传入实体本身 - 就像context.Find(settingWithTwoKeys))。

public static TEntity Find<TEntity>(this DbContext context, TEntity keyObject) 
{
    var entityType = context.Model.FindEntityType(typeof(TEntity));
    var pk = entityType.FindPrimaryKey();

    var keyArgs = new List<object>();
    foreach(var pkProperty in pk.Properties)
    {
        var propValueInKeyObject = pkProperty.PropertyInfo.GetValue(keyObject);
        keyArgs.Add(propValueInKeyObject);
    }

    return context.Find<TEntity>(keyArgs);
}

你的第二个问题 - 这是HasKey为了什么。只要您的数据库实现与 EF 约定不匹配,您就可以使用它。您的Setting实体就是一个很好的例子。EF 中没有允许它自动识别Name并且Version是 PK 的约定。您需要HasKey在模型构建器中使用来告诉它。


推荐阅读