简体   繁体   English

实体框架似乎用它们的实际值替换参数

[英]Entity Framework seems to replace parameters with their actual values

We're seeing a whole bunch of SQL errors in our logs about Must declare the scalar variable "@" or some such thing. 我们在日志中看到一大堆SQL错误, 必须声明标量变量“@”或其他类似的东西。 Tracing into the actual SQL that generates the error, it appears these are SQL statement that the Entity Framework generates. 跟踪生成错误的实际SQL,它们似乎是实体框架生成的SQL语句。 Here's an example: 这是一个例子:

SELECT TOP (1) 
    [Extent1].[AccountId] AS [AccountId], 
    [Extent1].[Username] AS [Username], 
    [Extent1].[EmployerId] AS [EmployerId], 
    [Extent1].[EmployeeId] AS [EmployeeId], 
    [Extent1].[SubscriberId] AS [SubscriberId], 
    [Extent1].[RelationshipCode] AS [RelationshipCode], 
    [Extent1].[AccountType] AS [AccountType], 
    [Extent1].[AccountStatus] AS [AccountStatus]
    FROM [dbo].[jc_Accounts] AS [Extent1]
    WHERE (@'Brunswick' = [Extent1].[Username]) OR ((@'Brunswick' IS NULL) AND ([Extent1].[Username] IS NULL))

The thing causing the error is that @'Brunswick' line, which is supposed to be the Username we're looking for. 导致错误的是@'Brunswick'行,它应该是我们正在寻找的用户名。 So, it's as if the Entity Framework is swapping @p0 or something with the actual value. 因此,就好像实体框架正在交换@ p0或具有实际值的东西。 We're also seeing tons of errors about things like @2892734 or some such, so numeric parameters are also affected. 我们也看到很多关于@ 2892734等问题的错误,所以数字参数也会受到影响。 For example: 例如:

WHERE ([Extent4].[AreaLevel] = 2) AND ([Extent1].[DimensionId] = [Extent4].[AreaId]) AND ([Extent5].[GroupId] = @106929) AND ([Extent5].[IsActive] = 1) AND ([Extent5].[AreaId] = [Extent1].[DimensionId])

Unfortunately, our database context and entity repository code is something you'd see in your worst nightmare. 不幸的是,我们的数据库上下文和实体存储库代码是您在最糟糕的噩梦中看到的。 A lot of it hasn't been touched in years, there's wrappers around wrappers around wrappers, things that use reflection to map POCOs to stored procedure calls, all sorts of fun stuff. 很多时候都没有涉及很多,包装器周围的包装器,使用反射将POCO映射到存储过程调用的东西,各种有趣的东西。 We've spent a ton of time on this and we haven't found anything that can shed some light on this issue. 我们花了很多时间在这上面,我们还没有找到任何可以解释这个问题的东西。

We've also upgraded Entity Framework from 4 to 5 to 6 and other versions in between, and this bug persists. 我们还将实体框架从4升级到5到6以及其他版本,这个bug仍然存在。 So I don't think it's a weird EF bug. 所以我不认为这是一个奇怪的EF错误。

My Question: 我的问题:

In what case would EF generate such a query? 在什么情况下EF会产生这样的查询? Or, if it's for sure some sort of custom thing we've extended the Entity Framework into doing, what sorts of extensions would I want to start looking at? 或者,如果确定某种自定义的东西我们已经实体框架扩展到了,我想要开始考虑哪种扩展? I'm looking for things I could search the code base for and get some clues. 我正在寻找可以搜索代码库的东西,并获得一些线索。

I don't need a full answer, I'm looking for some ideas from EF experts to get me headed down the right track. 我不需要一个完整的答案,我正在寻找EF专家的一些想法让我走上正轨。 I can add more details, just ask below. 我可以添加更多细节,请在下面提问。

It's weird indeed. 这确实很奇怪。 Even though you might not want to change your context, would it be reasonable to temporarily add some custom logging to it? 即使您可能不想更改上下文,临时添加一些自定义日志记录是否合理? Earlier today I happened to give that example in another post : 今天早些时候,我碰巧在另一篇文章中给出了这个例子:

public MyContext : DbContext
{
    private static ILog log = LogManager.GetCurrentClassLogger();

    public MyContext(string connectionString)
        : base(connectionString)
    {
        this.Database.Log = (msg) => log.Trace(msg);
    }
}

However, very temporarily, and in debug if you can reproduce the query, you could do something like that to break when it happens then crawl up the callstack : 但是, 非常暂时,并且在调试中如果您可以重现查询,您可以执行类似的操作,以便在它发生时中断然后爬上callstack:

public MyContext : DbContext
{
    private static ILog log = LogManager.GetCurrentClassLogger();

    public MyContext(string connectionString)
        : base(connectionString)
    {
        this.Database.Log = (msg) => 
        {
            if (msg.Contains("@'Brunswick'"))
                Debugger.Break();
        };
    }
}

If you fancy regex, or if you don't always get the same variable substitution, you could make msg match against "@ that isn't followed by 'p__linq__'", but I'll leave that to you! 如果你喜欢正则表达式,或者如果你不总是得到相同的变量替换,你可以使msg匹配“@后面没有'p__linq__'”,但我会把它留给你!

If i'm not mistaken, i already saw some of this and it was situation where we used for example Take(20) instead of Take(()=>20) 如果我没有弄错的话,我已经看到了一些这样的情况,我们用的例子是Take(20)而不是Take(()=>20)

or another case is var a = []{'a','b','c'} var res = context.Users.Where(u=>a.contains(u.Id)) 或者另一种情况是var a = []{'a','b','c'} var res = context.Users.Where(u=>a.contains(u.Id))

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

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