gpt4 book ai didi

c# - 使用 EF TPT 在多个表中搜索记录

转载 作者:行者123 更新时间:2023-11-30 15:58:44 29 4
gpt4 key购买 nike

我有一个带有 TPT 继承映射的项目,现在我需要给它添加一个搜索功能,以便在多个表中查找记录。这就是我目前拥有的:

public abstract class Customer
{
public int Id { get; set; }
public string Memo { get; set; }
...
}

public class Person : Customer
{
public string GivenName { get; set; }
public string Surname { get; set; }
...
}
public class Company : Customer
{
public string Name { get; set; }
...
}

我还有一个工作单元和一堆存储库,我需要将过滤功能添加到 CustomerRepository 的几个方法中。假设我有一个具有以下签名的 Count 方法

public int Count(System.Linq.Expressions.Expression<Func<Customer, bool>> filter = null)

现在我需要获取 GiveNameSurname 包含 searchTerm 的客户数量,以防客户是 PersonName 字段中的相同 searchTerm(如果是公司)。

长话短说
应如何实现具有单个可搜索分页列表的 Customers(同时包含 PersonCompany 类型)的 View ?我的意思是就带有签名的方法而言,例如 public IHttpActionResult Get(string searchTerm, int pageSize, int pageNumber)...

这就是我的尝试:
我向每个类添加了一个静态方法,该方法将生成一个 Expression 来搜索该特定类,这就是它查找 Person 类的方式:

public static System.Linq.Expressions.Expression<Func<Person, bool>> GetFilter(string searchTerm)
{
if (String.IsNullOrWhiteSpace(searchTerm))
{
return null;
}
var parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(Person));
System.Reflection.MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });

return System.Linq.Expressions.Expression.Lambda<Func<Person, bool>>(
System.Linq.Expressions.Expression.OrElse(
System.Linq.Expressions.Expression.Call(
System.Linq.Expressions.Expression.PropertyOrField(parameterExpression, "GivenName"),
method,
System.Linq.Expressions.Expression.Constant(searchTerm, typeof(string))
),
System.Linq.Expressions.Expression.Call(
System.Linq.Expressions.Expression.PropertyOrField(parameterExpression, "Surname"),
method,
System.Linq.Expressions.Expression.Constant(searchTerm, typeof(string))
)
), parameterExpression);
}

并尝试构建一个 Expression 来检查客户的类型,然后进行适当的数据检查,但在这里我遇到了困难......这就是我现在所拥有的:

    var parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(Customer));
var typeIsPerson = System.Linq.Expressions.Expression.TypeIs(parameterExpression, typeof(Person));
var typeIsCompany = System.Linq.Expressions.Expression.TypeIs(parameterExpression, typeof(Company));

var q = System.Linq.Expressions.Expression.Block(
System.Linq.Expressions.Expression.IfThen(typeIsPerson, Person.GetFilter(searchTerm)),
System.Linq.Expressions.Expression.IfThen(typeIsCompany, Company.GetFilter(searchTerm)),
System.Linq.Expressions.Expression.Constant(false));

var a = System.Linq.Expressions.Expression.Lambda<Func<Customer, bool>>(
q, parameterExpression);

这里我有两个问题(至少?),首先,当我尝试调用 Count 时,我遇到了一个非常不愉快的 NotSupportedException 异常,它显示 Unknown LINQ expression of type 'Block'。第二个是我不知道如何返回每个 GetFilters 的执行结果,我怀疑我会得到 false 任何记录,因为它是默认值那是我的 Block 中的最后一个 Expression...
可能是我走错了路,这是应该以完全不同的方式完成的事情吗?

最佳答案

LINQ to Entities 通常不支持表达式 block 。通常您不需要它们,因为您可以仅使用 C# 条件运算符 构建几乎任何表达式? :(映射到 Expression.Condition)。

但在尝试动态构建表达式之前,您需要找到一个 EF 支持的构造,该构造可与 TPT(和其他 EF 继承模型)多态查询一起使用。这并不容易,因为所有示例都使用 OfType 方法,该方法仅在您需要过滤具体的派生实体时适用。经过反复试验,幸运的是有两种受支持的结构 - isas(重要:as,而不是强制转换!)。

所以静态构建的谓词表达式可能是这样的:

Expression<Func<Customer, bool>> predicate = c =>
c is Person ?
((c as Person).GivenName.Contains(searchTerm) || (c as Person).Surname.Contains(searchTerm)) :
c is Company ?
(c as Company).Name.Contains(searchTerm) :
false;

(坦率地说,您不想查看生成的 SQL,但它可以工作)

现在您可以根据需要动态构建它。您已经找到了 is 表达式方法( Expression.TypeIs ),对于 as 运算符,对应的表达式方法是 Expression.TypeAs .

关于c# - 使用 EF TPT 在多个表中搜索记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42615818/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com