在 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,您将为大型数据库付出高性能代价,因为它将所有内容都放入内存。 IEnumerableIQueryable 慢,因为后者在数据库中独占执行。【参考方案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=&gt; 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】:

使用 mysqlSqlFunctions.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&lt;Int32&gt;

在过去几天的反复试验中,我花了很多时间搜索才能找到这个。

我希望这对一些程序员有所帮助。

【讨论】:

对我不起作用。它抛出异常“...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[]

实体框架 linq 主细节投影到自定义类

使用 Entity Framework Core 在 LINQ 查询中将字符串转换为 DateTime

在c#/LINQ中将数组转换为字符串的最短方法[重复]

实体框架 - 荒谬的查询,将 smallint 转换为 int 进行比较 [重复]