如何在 EF 中使用强类型 ID?

Posted

技术标签:

【中文标题】如何在 EF 中使用强类型 ID?【英文标题】:How to use strongly typed id in in EF? 【发布时间】:2021-11-22 17:41:13 【问题描述】:

我有原始的痴迷类 EmailAddress 已覆盖 ToString()

public class EmailAddress

   private string _value;

   public EmailAddress(string value)
   
        _value = value;
   

   public override string ToString()
   
        return _value;
   

我的域模型Customer 看起来像:

public class Customer

   public EmailAddress EmailAddress  get; set; 
   public string FullName get; set;  

我已经在 FluentApi 中为EmailAddress 配置了转换:

modelBuilder.Entity<Customer>().Property(x => x.EmailAddress)
                .HasConversion(
                x => x.ToString(),
                x => new EmailAddress(x));

我也有通用存储库模式,当我想过滤数据时:

public List<Customer> GetCustomers(GetCustomersQuery queryParameters)


  IQueryable<Customer> queryCustomers = _customerContext.GetAll();

  return queryCustomers.Where(x =>
         x.EmailAddress.ToString()
        .Contains(queryParameters.Email)).ToList();

我有一个错误:

无法翻译 LINQ 表达式 DbSet&lt;Customer&gt;().Where(t =&gt; t.EmailAddress.ToString()。额外的 信息:方法object.ToString的翻译失败。

我试过 EF 6.4 你有什么解决方法吗?

【问题讨论】:

为什么?为什么要使您的域过于复杂?您可以将 setter 内部化并引入一个公共方法/类来清理电子邮件。保持实体定义简单且实用。 【参考方案1】:

对于真正有动力,不怕复杂领域的人,我找到了解决方案

public class EmailAddress

   private string _value;

   public static explicit operator string(EmailAddress emailAddress) => emailAddress._value;

   public EmailAddress(string value)
   
        _value = value;
   

   public override string ToString()
   
        return _value;
   

查询是

queryCustomers.Where(x =>
         ((string)x.EmailAddress)
        .Contains(queryParameters.Email)).ToList();

此查询正在服务器端执行。

【讨论】:

请发布您的查询生成的 SQL,我很好奇。 去掉class EmailAddress直接使用字符串,你的问题就迎刃而解了。 @Robert 我很想看看生成了什么 SQL,仍然怀疑这不是客户端评估。

以上是关于如何在 EF 中使用强类型 ID?的主要内容,如果未能解决你的问题,请参考以下文章

EF CTP5 - 强类型急切加载 - 如何包含嵌套导航属性?

如何从强类型视图模型创建视图?

为应用程序命令公开强类型 ID?

我开发的开源项目,让.NET7中的EFCore更轻松地使用强类型Id

Primitive Obsession - 具有自动增量的强类型 int ID

使用 C# 9 的records作为强类型ID - 初次使用