在 Linq 中将 int 转换为字符串到实体的问题
Posted
技术标签:
【中文标题】在 Linq 中将 int 转换为字符串到实体的问题【英文标题】:Problem with converting int to string in Linq to entities 【发布时间】:2010-11-07 04:41:24 【问题描述】:var items = from c in contacts
select new ListItem
Value = c.ContactId, //Cannot implicitly convert type 'int' (ContactId) to 'string' (Value).
Text = c.Name
;
var items = from c in contacts
select new ListItem
Value = c.ContactId.ToString(), //Throws exception: ToString is not supported in linq to entities.
Text = c.Name
;
无论如何我可以做到这一点吗? 请注意,在 VB.NET 中使用第一个 sn-p 没有问题,它工作得很好,VB 很灵活,我无法习惯 C# 的严格性!!!
【问题讨论】:
.ToString() 也不适用于 VB 中的 LinqToEF。恕我直言,有点愚蠢。 @StingyJack,问题出在 ELINQ(linq 2 实体),因为它将您的代码转换为 SQL,当涉及到内部 ToString 请求时,它不知道如何翻译 ' ToString' 到 SQL。与 linq 2 对象不同,当没有翻译并且一切都是 CLR lambdas 时,它会直接在请求的对象上执行。 我只是对他们允许编译这种错误感到恼火,而且我不得不永远寻找一个简单的英文描述原因(没有法律和学术界) . 你是对的,但他们也是对的,他们不应该将所有 CLR 和自定义 CLR 功能转换为 SQL,尤其是在早期版本的 EF 中:) ToString,阅读 Brian 的回答:***.com/questions/1066760/… 很好,但是使用 3.5 而不是 4 的人呢?然后呢? 【参考方案1】:使用 EF v4,您可以使用 SqlFunctions.StringConvert
。 int 没有重载,因此您需要转换为双精度或小数。你的代码最终看起来像这样:
var items = from c in contacts
select new ListItem
Value = SqlFunctions.StringConvert((double)c.ContactId).Trim(),
Text = c.Name
;
【讨论】:
为什么它们不包含 int 的重载? @Nestor 这不适用于 SQL Compact。很难找到。 为了避免结果前的空格,你应该使用SqlFunctions.StringConvert((double)c.ContactId).Trim()
似乎不适用于使用 System.Data.SQLite 的 SQLite Typw 'System.Data.Objects.SqlClient 中的 Methode 'System.String StringConvert(System.Nullable`1[System.Double])' .SqlFunctions' kann nicht 在 einen Speicherausdruck für 'LINQ to Entities' übersetzt werden。 (不能翻译成“LINQ to Entities”)
优秀的答案!请注意,从您使用 EF 6 开始,该类已移至另一个命名空间。因此,在 EF 6 之前,您应该包含:“System.Data.Objects.SqlClient” 如果您更新到 EF 6,或者只是使用此版本,请包含:“System.Data.Entity.SqlServer” 通过包含不正确的命名空间EF6,代码编译得很好,但会引发运行时错误。我希望此说明有助于避免一些混淆。【参考方案2】:
我通过将整数到字符串的转换排除在查询之外来解决了类似的问题。这可以通过将查询放入对象来实现。
var items = from c in contacts
select new
Value = c.ContactId,
Text = c.Name
;
var itemList = new SelectList();
foreach (var item in items)
itemList.Add(new SelectListItem Value = item.ContactId, Text = item.Name );
【讨论】:
这是解决它的一种方法,但请记住,这会增加执行时间,如果你有大量的对象,这个 foreach 是矫枉过正...【参考方案3】:使用 LinqToObject : 联系人。AsEnumerable()
var items = from c in contacts.AsEnumerable()
select new ListItem
Value = c.ContactId.ToString(),
Text = c.Name
;
【讨论】:
谢谢。仅供参考,我正在尝试解决一个稍微不同的问题。我正在使用 LINQ to entity / lambda,这很有效。我试图将 Int 转换为 String 并使用“包含”来查找匹配的结果 --> 即 db.contacts.AsEnumerable().Where(c => c.ContactId.ToString().Contains(searchitem)).ToList(); ; 如果您调用AsEnumerable
,您将为大型数据库付出高性能代价,因为它将所有内容都放入内存。 IEnumerable
比 IQueryable
慢,因为后者在数据库中独占执行。【参考方案4】:
SqlFunctions.StringConvert 可以,但我觉得很麻烦,而且大多数时候,我并没有真正需要在 SQL 端执行字符串转换。
如果我想做字符串操作,我会先在 linq-to-entities 中执行查询,然后在 linq-to-objects 中操作字符串。在本例中,我想获取一组数据,其中包含联系人的全名和 ContactLocationKey,即两个 Integer 列(ContactID 和 LocationID)的字符串连接。
// perform the linq-to-entities query, query execution is triggered by ToArray()
var data =
(from c in Context.Contacts
select new
c.ContactID,
c.FullName,
c.LocationID
).ToArray();
// at this point, the database has been called and we are working in
// linq-to-objects where ToString() is supported
// Key2 is an extra example that wouldn't work in linq-to-entities
var data2 =
(from c in data
select new
c.FullName,
ContactLocationKey = c.ContactID.ToString() + "." + c.LocationID.ToString(),
Key2 = string.Join(".", c.ContactID.ToString(), c.LocationID.ToString())
).ToArray();
现在,我承认编写两个匿名选择确实很麻烦,但我认为这比执行 L2E 不支持的字符串(和其他)函数的便利性要重要。另请注意,使用此方法可能会降低性能。
【讨论】:
【参考方案5】:public static IEnumerable<SelectListItem> GetCustomerList()
using (SiteDataContext db = new SiteDataContext())
var list = from l in db.Customers.AsEnumerable()
orderby l.CompanyName
select new SelectListItem Value = l.CustomerID.ToString(), Text = l.CompanyName ;
return list.ToList();
【讨论】:
你测试过它并且它有效吗?阅读this之前的答案。 是的,我已经在使用它了。它适用于 MVC3、EF4、CTP5、SQL CE4。 这似乎比装箱加倍并使用 StringConvert 更优雅。 但是在这种情况下,您将从数据库中获取所有数据,然后假设您想在return list.ToList();
之前对此列表进行一些过滤!!
当您无法访问 SqlFunctions 时,您没有其他选择。但是,我会在查询中使用它:return (from l in db.Customers orderby l.CompanyName select new Id=l.CustomerID, Name=l.CompanyName).AsEnumerable().Select(c=> new SelectListItemValue=c.Id.ToString(), Text = c.Name).ToList();
。这样做只会从 db 中获取 id/name(而不是所有客户属性),并使用 db 上更有效的索引进行排序。【参考方案6】:
var selectList = db.NewsClasses.ToList<NewsClass>().Select(a => new SelectListItem(
Text = a.ClassName,
Value = a.ClassId.ToString()
);
先转换成object,然后toString()就正确了。
【讨论】:
【参考方案7】:Brian Cauthon 的回答非常棒!只是一点点更新,对于 EF 6,该类已移至另一个命名空间。因此,在 EF 6 之前,您应该包括:
System.Data.Objects.SqlClient
如果您更新到 EF 6,或者只是使用此版本,请包括:
System.Data.Entity.SqlServer
通过在 EF6 中包含不正确的命名空间,代码可以正常编译,但会引发运行时错误。我希望这个说明有助于避免一些混乱。
【讨论】:
我不得不说您的 答案也很出色。我升级到 EF6 并一直在到处寻找 SqlFunctions。您的回答为我指明了正确的方向。我只是补充一点,您还需要对 EntityFramework.SqlServer 的引用(您可能只有对 EntityFramework 的引用)。【参考方案8】:我在将 MVC 2 应用程序转换为 MVC 3 时遇到了同样的问题,只是为了给这个问题提供另一个(干净的)解决方案,我想发布我所做的......
IEnumerable<SelectListItem> producers = new SelectList(Services.GetProducers(),
"ID", "Name", model.ProducerID);
GetProducers() 只返回生产者的实体集合。 附: SqlFunctions.StringConvert 对我不起作用。
【讨论】:
【参考方案9】:如果您的“联系人”充当通用列表,我希望以下代码运行良好。
var items = contact.Distinct().OrderBy(c => c.Name)
.Select( c => new ListItem
Value = c.ContactId.ToString(),
Text = c.Name
);
谢谢。
【讨论】:
【参考方案10】:另一种解决方案:
c.ContactId + ""
只需添加空字符串,它就会被转换为字符串。
【讨论】:
返回错误:System.NotSupportedException:无法将类型“System.Int64”转换为类型“System.Object”。 LINQ to Entities 仅支持转换 EDM 基元或枚举类型。【参考方案11】:使用 mysql,SqlFunctions.StringConvert
对我不起作用。由于我在项目中的 20 多个地方使用了SelectListItem
,因此我想要一个能够在不扭曲 20 多个 LINQ 语句的情况下工作的解决方案。我的解决方案是对SelectedListItem
进行子类化,以提供一个整数设置器,它将类型转换从LINQ 中移开。显然,这个解决方案很难概括,但对我的具体项目很有帮助。
要使用,请创建以下类型并在您的 LINQ 查询中使用代替 SelectedListItem
并使用 IntValue 代替 Value。
public class BtoSelectedListItem : SelectListItem
public int IntValue
get return string.IsNullOrEmpty(Value) ? 0 : int.Parse(Value);
set Value = value.ToString();
【讨论】:
【参考方案12】:如果你使用实体框架并且你想让唯一的 int 可以接受,那么你可以在 linq 查询中使用它,你可以试试这个
var items = from c in contacts
select new ListItem
Value = (int)ContractId
Text = c.Name
;
它会起作用,因为使用 (int) 会将您的值转换为 int,因此您不需要将字符串转换为 int 并且您会得到想要的结果。
这在我的项目中对我有用,我认为这对你会有所帮助
【讨论】:
【参考方案13】:我的理解是,您必须创建一个部分类来“扩展”您的模型并添加一个只读属性,该属性可以利用该类的其余属性。
public partial class Contact
public string ContactIdString
get
return this.ContactId.ToString();
然后
var items = from c in contacts
select new ListItem
Value = c.ContactIdString,
Text = c.Name
;
【讨论】:
不,您不能在 LINQ to Entities(在 .NET 3.5 中)中使用自定义属性。 我没有测试它,但它也不会工作。因为它不是表字段属性。我可以先用 ToArray() 然后 linqing 对象,但我想查询数据库。我认为将无法做到这一点。我创建了自己的 ListItem,它采用一个 int 字段。这对我来说效果更好。【参考方案14】:var items = from c in contacts
select new ListItem
Value = String.Concat(c.ContactId), //This Works in Linq to Entity!
Text = c.Name
;
我发现SqlFunctions.StringConvert((double)c.Age)
对我不起作用,或者该字段的类型为Nullable<Int32>
在过去几天的反复试验中,我花了很多时间搜索才能找到这个。
我希望这对一些程序员有所帮助。
【讨论】:
对我不起作用。它抛出异常“...System.String Concat(System.Object)
不能被翻译成商店表达式...”。
对我也不起作用。我还收到“System.NotSupportedException:LINQ to Entities 无法识别方法 'System.String Concat(System.Object)' 方法,并且此方法无法转换为存储表达式。”
不起作用 - 使用此答案 [NotSupportedException: LINQ to Entities 无法识别方法 'System.String Concat(System.Object)' 方法,并且此方法无法转换为存储表达式。 ]【参考方案15】:
你可以试试:
var items = from c in contacts
select new ListItem
Value = Convert.ToString(c.ContactId),
Text = c.Name
;
【讨论】:
上面的代码将不起作用,因为它会抛出一个错误,说“LINQ to Entities 无法识别方法 'System.String ToString(Int32)' 方法,并且此方法无法转换为存储表达。”以上是关于在 Linq 中将 int 转换为字符串到实体的问题的主要内容,如果未能解决你的问题,请参考以下文章
为啥不能使用 SqlFunctions 在 LinQ 中将 int 转换为字符串?
使用 LINQ 在一行代码中将 string[] 转换为 int[]