在LINQ to Entities中如何拼接整数和字符串?

11
我正在使用以下代码:
from c in Country
 where c.IsActive.Equals(true)
 orderby c.CountryName
 select new
 {
     countryIDCode = c.CountryID + "|" + c.TwoDigitCode,
     countryName = c.CountryName
 }

但是当我运行它时,我收到以下错误:

无法将类型'System.Int32'转换为类型'System.Object'。LINQ to Entities仅支持将Entity Data Model基元类型强制转换。

CountryID是int类型,而TwoDigitCode是string类型。

如何正确地进行连接?

8个回答

23

使用 System.Data.Objects.SqlClient.SqlFunctions.StringConvert

 from c in Country
 where c.IsActive.Equals(true)
 orderby c.CountryName
 select new
 {
     countryIDCode = SqlFunctions.StringConvert((double)c.CountryID) 
                     + "|" + c.TwoDigitCode,
     countryName = c.CountryName
 }

我不是很确定。从我的角度来看,数据库类型一直表现得有些奇怪,而SqlFunctions实用程序是我用来解决像发布的这个问题的工具。我更喜欢这种方法,而不是像ToList转换这样不太明显的解决方案,因为它明确地显示了你对代码进行维护的任何人正在做什么。 - flyfisher1952
我认为这应该是被接受的答案,因为它解决了问题,而不像Nicholas Murray的答案那样引入性能惩罚(尽管它确实说“...并且是一个小数据集”)。 - Teodor Sandu
在EF6中,此方法已移至System.Data.Entity.SqlServer.SqlFunctions.StringConvert。 - jgerman

7

如果这个错误阻止了您的进展,并且数据集很小,您可以通过枚举查询(调用ToList)来从数据库中获取数据。从那时起,您的操作将针对内存中的对象,您可能不会遇到您正在接收的错误。

var countries = (from c in Country
where c.IsActive.Equals(true)
orderby c.CountryName
select c).ToList();


var countryCodes = (from c in countries
where c.IsActive.Equals(true)
    orderby c.CountryName
    select new
    {
        countryIDCode = c.CountryID + "|" + c.TwoDigitCode,
        countryName = c.CountryName
    });

7
我认为这个答案已经过时并且是一个很糟糕的实践。这只是一个快速而肮脏的修复方法,虽然现在能用,但以后会有问题(例如当你当前的小数据集突然增长,或者客户决定在另一个更大的数据集上需要完全相同的东西时)。请参考flyfisher1952的答案,他直接使用数据库函数来解决问题,这是比这个答案更好的解决方法。 - Teodor Sandu

5

本主题包含可以转换为命令树规范函数并在服务器上执行的CLR方法列表:

MSDN

对于不在此列表中的CLR方法,您需要使用.AsEnumerable()将结果拉到客户端,并执行LINQ to Objects查询。


3

这是旧版本Entity Framework的一个限制。我认为在v4中已经解决了。对于您的版本,解决方法是将结果转换为可枚举对象:

from a in 
(from c in Country
where c.IsActive.Equals(true)
orderby c.CountryName).AsEnumerable()
select new
{
    countryIDCode = a.CountryID + "|" + a.TwoDigitCode,
    countryName = a.CountryName
}

我正在尝试您的方法,但是我遇到了编译时错误:查询体必须以select子句或group子句结尾。 - Waheed
你展示的查询在EF 1和4中都可以更或少地正常工作。 - Craig Stuntz
是的,但我不确定您是否仍需要在v4中使用此解决方法,或者限制是否已经解决。 - David Espart
3
正在使用EF4时遇到了相同的错误。找到了你的答案并使用AsEnumerable()解决了它。现在真的更喜欢L2S而不是EF4.... - Graham

3

对于将int转换为字符串,没有标准函数映射

因此,只需在2个不同的列中返回IntString,然后在使用AsEnumerable方法后在.NET中进行连接:

var cListTemp = from c in Country
    where c.IsActive.Equals(true)
    orderby c.CountryName
    select new
    {
        countryID = c.CountryID,
        twoDigitCode = c.TwoDigitCode,
        countryName = c.CountryName
    };

var cList = cListTemp.AsEnumerable().Select(c => new {
    countryIDCode = c.countryID + "|" + c.twoDigitCode,
    countryName = c.countryName
});

2

我可以使用以下代码连接字符串:

l.StateName + " " + SqlFunctions.StringConvert( (double?)l.Zip ).Trim()

看起来只需要SqlFunctions.StringConvert((double?)l.Zip)就足够了,但结果字符串左侧有很多填充字符,导致字符串比较不匹配。事实证明,Trim()可以去掉多余的字符。我相信SqlFunctions.StringConvert((double?)l.Zip).Trim()有效地转换为SQL:LTrim(RTrim(STR(Zip)))


-3
使用 c.CountryId.ToString() 来获取您的 CountryId 的字符串表示形式,并将其连接到 TwoDigitCode 字段中:
from c in Country
 where c.IsActive.Equals(true)
 orderby c.CountryName
 select new
 {
     countryIDCode = c.CountryID.ToString() + "|" + c.TwoDigitCode,
     countryName = c.CountryName
 }

我希望你的错误确实是编译器错误(我想不出编译器如何允许这个查询。但我不知道它如何知道有关Linq to Entities部分的信息)。


2
不行,这个不能使用。在这种情况下会出现以下错误:LINQ to Entities 不认识 'System.String ToString()' 方法,而且这个方法无法被转换成存储表达式。 - Waheed
1
“.ToString()”和“.Format()”不能在SQL客户端上执行,因此会导致运行时错误。 - gingerbreadboy
1
在L2S中运行良好,你可能正在使用EF。虽然没有理由给它点踩,但你应该更明确一些。 - Johannes Rudolph

-3
如果您需要将它们拼接成一个字符串,您可以使用 String.Format 方法:
countryIDCode = String.Format("{0}|{1}", c.CountryID, c.TwoDigitCode)

1
不,这会产生运行时错误:LINQ to Entities不识别'System.String Format(System.String, System.Object, System.Object)' 方法,并且该方法无法转换为存储表达式。 - Waheed
1
".ToString()"和".Format()"不能在SQL客户端上执行,因此会导致运行时错误。 - gingerbreadboy
3
好的,问题是“在LINQ中连接int和string”,而不是在Linq To SQL等中。原帖作者应该更清楚明确。LINQ!= SQL。 - Dan Diplo
问题也被提问者错误地标记了。+1 回答提问者所的问题,即使这不是他真正想要的。 - Craig Stuntz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接