在Linq中将int转换为字符串到实体的问题


202
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中使用第一个片段没有问题,它工作得很好,VB灵活,我无法适应C#的严格性!!!


2
.ToString()也不适用于VB中的LinqToEF。恕我直言,有点愚蠢。
StingyJack 2010年

5
@StingyJack,问题出在ELINQ(linq 2实体)上,因为它将代码转换为SQL,当涉及到内部ToString请求时,它不知道如何将“ ToString”转换为SQL。与linq 2对象不同,当没有翻译并且所有内容都是CLR lambda时,它将直接在所请求的对象上执行。
Shimmy Weitzhandler,2010年

1
我很生气,因为他们允许编译这种错误,并且我不得不永远拖延才能找到原因的简单英语描述(无法律用语和学术用语)。
StingyJack 2010年

1
您是对的,但他们也是对的,不应该将所有CLR和自定义的CLR功能转换为SQL,尤其是在EF的早期版本中:)关于ToString,请阅读Brian的回答:stackoverflow。 com / questions / 1066760 /…
Shimmy Weitzhandler,2010年

太好了,但是使用3.5(不是4)的人呢?那呢

Answers:


313

使用EF v4,您可以使用SqlFunctions.StringConvert。int没有重载,因此您需要转换为双精度或十进制。您的代码最终看起来像这样:

var items = from c in contacts
            select new ListItem
            {
                Value = SqlFunctions.StringConvert((double)c.ContactId).Trim(),
                Text = c.Name
            };

234
为什么在地球上它们不包含int的重载?
Jeremy Coenen

7
@Nestor这不适用于SQL Compact。发现困难的方法。
奥斯汀

24
为了避免在结果前出现空格,您应该使用SqlFunctions.StringConvert((double)c.ContactId).Trim()
Kim Tranjan

2
似乎不适用于使用System.Data.SQLite的SQLite。从“ LINQ to Entities”到übersetztwerden。(无法翻译为“ LINQ to Entities”)
OneWorld

5
很好的答案!请注意,从使用EF 6开始,该类已移至另一个名称空间。因此,在EF 6之前,您应该包括:“ System.Data.Objects.SqlClient”如果更新到EF 6,或者只是在使用此版本,请包括:“ System.Data.Entity.SqlServer”。 EF6,代码可以很好地编译,但是会引发运行时错误。我希望此注释有助于避免混淆。
狮子座

12

我通过将整数到字符串的转换置于查询之外,解决了类似的问题。这可以通过将查询放入对象中来实现。

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是过大的……
Serlok

9

使用LinqToObject:联系人。AsEnumerable()

var items = from c in contacts.AsEnumerable()
            select new ListItem
            {
                Value = c.ContactId.ToString(),
                Text = c.Name
            };

谢谢。仅供参考,我正在尝试解决一个稍微不同的问题。我对实体/ lambda使用LINQ,这有效。我正在尝试将Int转换为String并使用“包含”来查找匹配结果->即db.contacts.AsEnumerable()。Where(c => c.ContactId.ToString()。Contains(searchitem))。ToList (); ;
ejhost 2014年

9
如果您致电,AsEnumerable您将为大型数据库支付较高的性能价格,因为它将所有内容带入内存。IEnumerable与之相比,速度较慢,IQueryable因为后者仅在数据库中执行。
CodeArtist 2015年

5

SqlFunctions.StringConvert可以使用,但是我发现它很麻烦,而且在大多数情况下,我并不需要在SQL端执行字符串转换。

如果要进行字符串处理,该怎么做是先在linq-to-entities中执行查询,然后再在linq-to-objects中处理字符串。在此示例中,我想获取一组包含联系人全名和ContactLocationKey的数据,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中不支持的字符串(和其他)函数。还请记住,使用此方法可能会降低性能。


4
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();
            }
        }

您是否测试过并且可以正常工作?请先阅读答案。
Shimmy Weitzhandler,2011年

是的,我已经在使用它。它适用于MVC3,EF4,CTP5,SQL CE4。
内斯特

这似乎比将其装箱并使用StringConvert进行装箱更为优雅。
CmdrTallen 2011年

9
但是在这种情况下,您将从数据库中获取所有数据,然后假设您想在此列表之前进行过滤return list.ToList();
瓦希德·比塔尔

4
当您无法访问SqlFunctions时,您没有其他选择。但是,我会在查询中使用它return (from l in db.Customers orderby l.CompanyName select new {Id=l.CustomerID, Name=l.CompanyName}).AsEnumerable().Select(c=> new SelectListItem{Value=c.Id.ToString(), Text = c.Name}).ToList();。这样做只能从数据库中获取ID /名称(而不是所有客户属性),并使用数据库上更有效的索引进行排序。
Brian Cauthon 2011年

3
var selectList = db.NewsClasses.ToList<NewsClass>().Select(a => new SelectListItem({
    Text = a.ClassName,
    Value = a.ClassId.ToString()
});

首先,转换为对象,然后toString()将是正确的。


3

Brian Cauthon的答案非常好!对于EF 6,只需稍作更新,该类便移至另一个名称空间。因此,在EF 6之前,您应包括:

System.Data.Objects.SqlClient

如果您更新到EF 6,或者只是使用此版本,请包括:

System.Data.Entity.SqlServer

通过在EF6中包含不正确的名称空间,代码可以很好地编译,但会引发运行时错误。我希望此注释有助于避免混淆。


我不得不说,您的回答也很好。我升级到EF6,并且到处都在寻找SqlFunctions。您的回答为我指明了正确的方向。我将添加您还需要对EntityFramework.SqlServer的引用(您可能仅对EntityFramework的引用)。
Metalogic

2

当我将我的MVC 2应用程序转换为MVC 3时遇到了同样的问题,只是为了给这个问题提供另一个(干净的)解决方案,我想发布我所做的...

IEnumerable<SelectListItem> producers = new SelectList(Services.GetProducers(),
    "ID", "Name", model.ProducerID);

GetProducers()仅返回生产者的实体集合。PS SqlFunctions.StringConvert对我不起作用。


2

如果您的“联系人”充当通用列表,我希望以下代码能正常工作。

var items = contact.Distinct().OrderBy(c => c.Name)
                              .Select( c => new ListItem
                              {
                                Value = c.ContactId.ToString(),
                                Text = c.Name
                              });

谢谢。


2

另一种解决方案:

c.ContactId + ""

只需添加空字符串,它将被转换为字符串。


返回的错误:System.NotSupportedException:无法将类型“ System.Int64”强制转换为类型“ System.Object”。LINQ to Entities仅支持强制转换EDM基本类型或枚举类型。
QMaster

1

使用MySql,SqlFunctions.StringConvert对我不起作用。由于我SelectListItem在项目中使用了20多个位置,因此我希望找到一种能够在不扭曲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(); }
    }
}

1

如果您使用实体框架,并且希望使唯一的int可以接受,则可以在linq查询中使用它,您可以尝试此

var items = from c in contacts
        select new ListItem
        {
            Value = (int)ContractId 
            Text = c.Name
        };

它会起作用,因为使用(int)会将您的值转换为int,因此您不需要将字符串转换为int即可获得所需的结果。

这在我的项目中为我工作,我认为这对您有帮助


-2

我的理解是,您必须创建一个局部类以“扩展”模型并添加一个只读属性,该属性可以利用该类的其余属性。

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中)。
2009年

1
我没有对其进行测试,但是它也不起作用。因为它不是表字段属性。我可以先使用ToArray()进行操作,然后对对象进行临清操作,但是我想查询数据库。我认为将无法做到。我创建了一个带有int字段的列表项。这对我来说更好。
Shimmy Weitzhandler,2009年

-2
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>

在最近的尝试和错误中,我花了很多时间进行搜索以找到此内容。

我希望这对那里的一些编码人员有所帮助。


1
对我不起作用。它将引发异常“ ... System.String Concat(System.Object)无法转换为商店表达式... ”。
Slauma 2013年

1
也不适合我。我还收到“ System.NotSupportedException:LINQ to Entities无法识别方法'System.String Concat(System.Object)',并且该方法无法转换为商店表达式。”
camainc 2013年

1
不起作用-致力于解决此问题[NotSupportedException:LINQ to Entities无法识别方法'System.String Concat(System.Object)',并且该方法无法转换为商店表达式。]
Philipp Munin

-6

你能试一下吗:

var items = from c in contacts
        select new ListItem
        {
            Value = Convert.ToString(c.ContactId), 
            Text = c.Name
        };

上面的代码将不起作用,因为它将引发一个错误:“ LINQ to Entities无法识别方法'System.String ToString(Int32)',并且该方法无法转换为商店表达式”。
GK
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.