为什么实体框架不能在LINQ语句中使用的ToString()?为什么实体框架不能在LINQ语句中使用

2019-05-12 06:56发布

这个工作在LINQ到SQL:

var customersTest = from c in db.Customers
                select new
                {
                    Id = c.Id,
                    Addresses = from a in db.Addresses where c.Id.ToString() == 
                        a.ReferenzId select a
                };

foreach (var item in customersTest)
{
    Console.WriteLine(item.Id);
}

但在实体框架类似的例子获取说基本上是不能“它翻译成SQL”的错误信息 ,这里是德国原来的错误信息:

“‘LINQ到实体’的方法不能识别‘System.String的ToString()’,并且这种方法不能被翻译成表达店”。

翻译:

“‘LINQ到实体’不能识别方法‘System.String的ToString()’,这种方法不能被翻译成存储器表达。

任何人都了解我们如何能得到这种说法在实体框架的工作或解释为什么它得到这个错误任何光线?

Answer 1:

简单地说:LINQ到实体不知道从你的ID类型为字符串转换。

是什么类型c.ID ? 是否有任何理由为什么它是一个类型ID,但另一个用于ReferenzId ? 如果可能的话,让他们同一类型,这时你不会有问题了。 我不知道是否有LINQ执行转换到实体的其他方面 - 有可能是 - 但比对类型会更干净。

顺便说一句,这真的看起来就像是一个连接:

var query = from c in db.Customers
            join a in db.Addresses on c.Id equals a.ReferenzId into addresses
            select new { Id = c.Id, Addresses = addresses };

编辑:为了回答您的评论- ToString ,因为编译器有什么您的查询将意味着或将如何被翻译没有真正的想法出现在智能感知。 这是完全合法的C#,并能产生一个有效的表达式树 - 它只是EF不知道如何给表达式树转换成SQL。

你可以尝试使用Convert.ToString(c.Id)而不是仅仅调用c.Id.ToString() ...



Answer 2:

更新的答案:

如果你按照我给你我的回答开始的链接,这缺少的功能已同时未收到75票 ,现在(终于!) 微软在EF 6.1中实现 。 所有谁参加:感谢您的投票! 你的声音也没有。

例如:

var query = from e in context.Employees where e.EmployeeID.ToString() == "1" select e;

现在被翻译成:

DECLARE @p0 NVarChar(1000) = '1'
SELECT [t0].[EmployeeID], [t0].[LastName], [t0].[FirstName], [t0].[Title], 
    [t0].[TitleOfCourtesy], [t0].[BirthDate], [t0].[HireDate], [t0].[Address],[t0].[City],
    [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[HomePhone], [t0].[Extension], 
    [t0].[Photo], [t0].[Notes], [t0].[ReportsTo], [t0].[PhotoPath]
FROM [Employees] AS [t0]
WHERE (CONVERT(NVarChar,[t0].[EmployeeID])) = @p0

e.EmployeeID.ToString()转化为(CONVERT(NVarChar,[t0].[EmployeeID]))


原来的答案:

这是没有意义的,我为什么Linq2EF不翻译.ToString()为适当的SQL语句,LINQ2SQL确实,只有微软的开发团队知道他们为什么没有实现它尚未原因。 :-(

但是你可以提高优先级,如果你按照投票支持此功能来实现它这个链接。

幸运的是,还有2个解决方法可用 ,他们两个我在EF查询最近使用过的:


我)有什么帮助我解决这个限制是更改查询到一个列表 ,就像这样:

var customersList = (from c in db.Customers
             select c).ToList(); // converts to IEnumerable<T> ...
var customersTest = (from c in customersList 
             select new {Id=c.ID.ToString()}); // ... which allows to use .ToString()

语句.ToList()转换成IEnumerable<T>其中.ToString()是可用的。 需要注意的是,根据不同的需求,你可以使用.AsEnumerable()为好,这有延迟执行支持,这是更好,如果你有这取决于对方,或者如果您正在使用不同的参数值(多LINQ查询的优点非常感谢Divega这暗示!)。

此后,如你所愿,例如,你可以使用此查询:

var customersTest2 = from c in customersTest                 
    select new
            {
                Id = c.Id,
                Addresses = from a in db.Addresses where c.Id == a.ReferenzId select a
            };

当然,如果你需要,你可以到的对象添加更多的属性customersTest的要求。 您还可以优化上面的查询,我只用这个例子的可读性3个步骤。


II)对于简单的转换,如果你有重用在进一步的子查询生成的查询(和它需要保持IQueryable ),使用SqlFunctionsSystem.Data.Objects.SqlClient ,他们将被正确地转换成SQL查询。

实施例1:日期转换(你必须使用的日期部分,如下所示)

var customersTest = from c in db.Customers
    select new {
        strDate=SqlFunctions.DateName("dd", c.EndDate)
            +"."+SqlFunctions.DateName("mm", c.EndDate)
            +"."+SqlFunctions.DateName("yyyy", c.EndDate) 
    }

实施例2:数字到字符串转换

var customersTest = from c in db.Customers
    select new {
        strID=SqlFunctions.StringConvert((double)c.ID)
    }

这应该可以帮助你摆脱在需要转换为字符串大多数情况。




Answer 3:

实体框架6.1 RTM刚刚发布,现在支持的ToString()



Answer 4:

LINQ到实体,据我所知(对于V1)非常灵长类动物。 。换句话说,它不知道如何利用扩展方法“的ToString()”,并为它生成的SQL。

在LINQ to SQL时,其执行扩展方法“的ToString()”生成SQL之前。 不同的是,LINQ到实体使用IQueryable的,而不是IEnumerable的。

但是从我记得铸造应该工作(因为铸造是一种数据类型和SQL知道CAST())。

所以

c.Id.ToString()确实应该(串)c.Id

(也确保它是(串),而不是(字符串))。

其中一个挫折,我会说关于使用lambda(实体框架)来生成SQL表达式,而不是纯粹的LINQ的。

请记住一点,就是采用CAST上等号的左边登录SQL有点生病执行:-)



文章来源: Why would Entity Framework not be able to use ToString() in a LINQ statement?