简体   繁体   English

EF Core LINQ 表达式 'DbSet() 无法翻译

[英]EF Core The LINQ expression 'DbSet() could not be translated

What am I missing here?我在这里错过了什么?

IQueryable<IsActiveCustomerProviderRefDto> search =
    from customerProviderRef in _database.CustomerProviderRef
    join customerTrade in _database.CustomerTrade on customerProviderRef.ExternalRefId equals customerTrade.CustomerProviderRef into ctJoin
    from customerTradeJoin in ctJoin.DefaultIfEmpty()
    select new IsActiveCustomerProviderRefDto
    {
        CustomerProviderRef = customerProviderRef.ExternalRefId
    };

search = search.Where(e => e.CustomerId.Equals(find.customerProviderRef.CustomerId));

return search.FirstOrDefault();

Generates the following error:生成以下错误:

Description:The LINQ expression 'DbSet().Where(c => new IsActiveCustomerProviderRefDto{ CustomerProviderRef = c.ExternalRefId }.CustomerId.Equals("1014706150563885056"))' could not be translated.说明:LINQ 表达式 'DbSet().Where(c => new IsActiveCustomerProviderRefDto{ CustomerProviderRef = c.ExternalRefId }.CustomerId.Equals("1014706150563885056"))' 无法翻译。 Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。 See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.(Source: Microsoft.EntityFrameworkCore)有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038 。(来源:Microsoft.EntityFrameworkCore)

I've tried replacing the FirstOrDefault() call with ToList(), etc but makes no difference.我试过用 ToList() 等替换 FirstOrDefault() 调用,但没有任何区别。

I'm not entirely sure if my query is spot on either, so I'll provide a SQL version of the query I was attempting to achieve (LINQ is not my specialty)...我不完全确定我的查询是否准确,所以我将提供我试图实现的查询的 SQL 版本(LINQ 不是我的专长)...

SELECT *
FROM CustomerProviderRef [R]

LEFT OUTER JOIN [CustomerTrade] [T]
    ON [R].[ExternalRefId] = [T].[CustomerProviderRef]

WHERE
    [T].[Id] IS NULL -- essentially where the left outer join fails.
AND
    [R].[CustomerId] = @CustomerId

That query looks a bit off, in that you are doing the Where clause after the projection ( Select ) which I don't believe would compile.该查询看起来有点偏离,因为您在投影 ( Select ) 之后执行 Where 子句,我认为它不会编译。 The Where clause would expect to be limited to just the values that were selected. Where 子句预计仅限于所选的值。

The main issue will be based on what "find" represents in your example.主要问题将基于您的示例中“查找”所代表的内容。 Linking IQueryable queries in EF is possible when EF is happy they can be translated into a single SQL statement, but generally you should avoid it if at all possible.当 EF 满意时,可以在 EF 中链接IQueryable查询,它们可以转换为单个 SQL 语句,但通常您应该尽可能避免它。 Manually joining DbSets should be reserved for relationships which cannot be represented in the database with actual FK constraints.手动加入 DbSets 应该保留给那些不能在数据库中用实际 FK 约束表示的关系。 These are de-normalized relationships, usually hacks to "save space" but result in slow, buggy querying.这些是非规范化的关系,通常是为了“节省空间”而进行的黑客攻击,但会导致缓慢、错误的查询。 An example would be something like an Address table with an OwnerType and OwnerId Where OwnerType might be "Customer" or "Business" or several other values, used to define whether the OwnerId should pair to the CustomerId or BusinessId etc. These are slow and buggy because they cannot benefit from FKs or constraints for performance or data integrity.一个例子类似于带有 OwnerType 和 OwnerId 的地址表,其中 OwnerType 可能是“Customer”或“Business”或其他几个值,用于定义 OwnerId 是否应与 CustomerId 或 BusinessId 等配对。这些速度慢且有问题因为他们无法从 FK 或性能或数据完整性约束中获益。

EF and Linq should not be viewed as a like-for-like replacement for SQL using explicit joins between DbSets. EF 和 Linq 不应被视为使用 DbSet 之间的显式连接对 SQL 的同类替代。 Instead, set up the relationships between entities using Navigation properties with 1-to-many, many-to-one, many-to-many, or 1-to-1 relationships as the database schema structure reflects through FK references.相反,使用具有一对多、多对一、多对多或一对一关系的导航属性设置实体之间的关系,因为数据库模式结构通过 FK 引用反映。 This is what EF is designed to do, to generate SQL to pull back the applicable data from a object model representation of that related data.这就是 EF 旨在执行的操作,生成 SQL 以从该相关数据的 object model 表示中拉回适用数据。

based on the query with the relationship (1-to-many between CustomerProviderRef and CustomerTrade on ExternalRefId your Linq query would look more like:基于具有关系的查询(CustomerProviderRef 和 ExternalRefId 上的 CustomerTrade 之间的一对多关系,您的 Linq 查询看起来更像:

var results = dbContxt.CustomerProviderRef
    .Where(x => x.CustomerId == customerId
       && !x.CustomerTrades.Any())
    .ToList();

This assumes that there are multiple CustomerProviderRef per CustomerID and you want the ones that have no Trades.这假定每个 CustomerID 有多个 CustomerProviderRef,并且您想要那些没有交易的。

If there is only one expected CustomerProviderRef for a given customer you want to load it and determine if it has any trades:如果给定客户只有一个预期的 CustomerProviderRef,您想要加载它并确定它是否有任何交易:

var customerProviderRef = dbContxt.CustomerProviderRef
    .Include(x => x.CustomerTrades)
    .Where(x => x.CustomerId == customerId)
    .Single();

bool hasTrades = customerProviderRef.CustomerTrades.Any();

This eager loads the trades with the customer, which will fetch any trades when we load this customer's data.这急切地加载与客户的交易,这将在我们加载该客户的数据时获取任何交易。 EF will work out the joins as neded. EF 将根据需要计算连接。 From there we can check if the customer has any trades, and add Trades to that CustomerTrades collection and call SaveChanges() on the DbContext and EF will create the row and associate the FKs automatically.从那里我们可以检查客户是否有任何交易,并将交易添加到该 CustomerTrades 集合并调用 DbContext 上的SaveChanges() ,EF 将创建行并自动关联 FK。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM