Linq içindeki int'in dizeye varlıklara dönüştürülmesiyle ilgili sorun


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
            };

Bunu başarabileceğim yine de var mı? VB.NET'te sorun yok sadece harika çalışıyor ilk snippet'i kullanmak, VB esnek, C # 's katılığına alışmak im im !!!


2
.ToString () de VB'de LinqToEF için çalışmaz. IMHO, Bir tür aptal.
StingyJack

5
@StingyJack, sorun ELINQ (linq 2 varlıkları) ile ilgilidir, çünkü kodunuzu SQL'e çevirir ve bir iç ToString isteği söz konusu olduğunda, 'ToString'i SQL'e nasıl çevireceğini bilmez. Linq 2 nesnelerinden farklı olarak, çeviri olmadığında ve her şey CLR lambdas olduğunda, doğrudan istenen nesneler üzerinde gerçekleştirilir.
Shimmy Weitzhandler

1
Sadece bu tür bir hatanın derlenmesine izin verdikleri ve nedenin sade bir İngilizce açıklaması bulmak için sonsuza kadar troll etmek zorunda olduğumdan rahatsız oldum (sans legal-akademi ve akademi).
StingyJack

1
Haklısınız, ama aynı zamanda haklılar, tüm CLR ve özelleştirilmiş CLR işlevlerini özellikle EF'in ilk sürümünde değil SQL'e çevirmeleri gerekiyor :) ToString hakkında Brian'ın cevabını okuyun: stackoverflow. com / sorular / 1066760 /…
Shimmy Weitzhandler

Harika, ama 3.5, No 4 kullanan insanlar? Sonra ne?
Ekaterina

Yanıtlar:


313

EF v4 ile kullanabilirsiniz SqlFunctions.StringConvert. İnt için aşırı yük yoktur, bu nedenle bir çifte veya ondalığa atmanız gerekir. Kodunuz şöyle görünür:

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

235
Neden dünyada int için aşırı yük içermiyorlar?
Jeremy Coenen

7
@Nestor Bu, SQL Compact için çalışmaz. Bunu zor yoldan buldum.
Austin

24
SqlFunctions.StringConvert((double)c.ContactId).Trim()
Sonuçtan

2
System.Data.SQLite kullanarak SQLite için çalışmaz gibi görünüyor Speicherausdruck içinde Typew 'System.Data.Objects.SqlClient.SqlFunctions' kann nicht 'System.String StringConvert (System.Nullable`1 [System.Double])' yöntemi für 'LINQ to Entities' übersetzt werden. ("LINQ to Entities" e çevrilemez)
OneWorld

5
Mükemmel cevap! Lütfen dikkat edin, EF 6'yı kullanmaya başladığınızda, sınıf başka bir ad alanına taşındı. Bu nedenle, EF 6'dan önce şunları eklemelisiniz: "System.Data.Objects.SqlClient" EF 6'ya güncelleme yaparsanız veya sadece bu sürümü kullanıyorsanız şunları içerir: "System.Data.Entity.SqlServer" Yanlış ad alanını ekleyerek EF6, kod iyi derlenecek ama bir çalışma zamanı hatası verecektir. Umarım bu not biraz karışıklıktan kaçınmaya yardımcı olur.
Leo

12

Ben sorgu dışında dize tamsayı dönüşüm yerleştirerek benzer bir sorunu çözdü. Bu, sorguyu bir nesneye koyarak elde edilebilir.

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

Bu çözmenin bir yoludur, ancak bunun çok fazla nesneye sahipseniz, bu yürütme süresini artıracağını aklınızda bulundurun, bu foreach aşırıya
kaçar

9

LinqToObject: kişileri kullanın. AsEnumerable ()

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

Teşekkürler. Bilginize, biraz farklı bir sorunu çözmeye çalışıyorum. Varlıkları / lambda için LINQ kullanıyorum ve bu çalışıyor. Int bir String dönüştürmek ve eşleşen sonuçları bulmak için "içerir" kullanmaya çalışıyordum -> yani db.contacts.AsEnumerable (). Nerede (c => c.ContactId.ToString (). Içerir ( searchitem )). (); ;
ejhost

9
Aradığınızda AsEnumerable, daha büyük veritabanlarında yüksek performans ödersiniz, çünkü her şeyi belleğe getirir. IEnumerableile karşılaştırıldığında daha yavaştır, IQueryableçünkü daha sonra sadece veritabanında yürütülür.
CodeArtist

5

SqlFunctions.StringConvert işe yarayacak, ama hantal buluyorum ve çoğu zaman, SQL tarafında dize dönüştürme gerçekleştirmek için gerçek bir ihtiyaç yok.

Dize manipülasyonları yapmak istersem ne önce ilk linq-to-varlıklarda sorgu gerçekleştirmek, sonra linq-nesnelerde sokmaları manipüle etmektir. Bu örnekte, bir Kişi tam adı ve iki Tamsayı sütun (ContactID ve LocationID) dize birleştirme olan ContactLocationKey içeren bir veri kümesi elde etmek istiyorum.

// 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();

Şimdi, iki anonim seçim yazmak zorunda kalmayı kabul ediyorum, ancak L2E'de desteklenmeyen dize (ve diğer) işlevleri gerçekleştirebileceğiniz kolaylıktan daha ağır bastığını iddia ediyorum. Ayrıca, bu yöntemi kullanarak muhtemelen bir performans cezası olduğunu unutmayın.


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

Test ettiniz ve işe yarıyor mu? bu cevabı daha önce okuyun .
Shimmy Weitzhandler

Evet, zaten kullanıyorum. MVC3, EF4, CTP5, SQL CE4 için çalışır.
Nestor

Bu, boks yapmak ve StringConvert'i kullanmaktan daha zarif görünüyor.
CmdrTallen

9
Ancak bu durumda, veritabanındaki tüm verileri alırsınız ve daha önce bu listede biraz filtreleme yapmak istediğinizi varsayalım return list.ToList();!!
Wahid Bitar

4
SqlFunctions'a erişemediğinizde bundan başka seçeneğiniz yoktur. Ancak, Sorgumda bu kullanırdı: 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();. Bu şekilde yapmak sadece id / name db (tüm müşteri özellikleri yerine) alır ve db üzerinde daha verimli bir dizin kullanarak sıralama yapar.
Brian Cauthon

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

İlk olarak, nesneye dönüştürün, sonra toString () doğru olacaktır.


3

Brian Cauthon'un cevabı mükemmel! Sadece küçük bir güncelleme, EF 6 için, sınıf başka bir isim alanına taşındı. Bu nedenle, EF 6'dan önce şunları eklemelisiniz:

System.Data.Objects.SqlClient

EF 6'ya güncelleme yaparsanız veya yalnızca bu sürümü kullanıyorsanız şunları ekleyin:

System.Data.Entity.SqlServer

EF6 ile yanlış ad alanı ekleyerek kod iyi derlenecek, ancak bir çalışma zamanı hatası verecektir. Umarım bu not biraz karışıklıktan kaçınmaya yardımcı olur.


Bunu söylemek zorunda da cevap da mükemmel. EF6'ya geçtim ve her yerde SqlFunctions'ı arıyordum. Cevabınız bana doğru yönü gösterdi. Sadece EntityFramework.SqlServer için bir referansa ihtiyacınız olduğunu ekleyeceğim (sadece EntityFramework için bir referansınız olabilir).
Katalog

2

Ben MVC 2 app MVC 3 dönüştürürken ve sadece bu soruna başka (temiz) bir çözüm vermek için ben aynı şeyi koştu ne yaptığımı göndermek istiyorum ...

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

GetProducers (), yalnızca Producers'ın varlık koleksiyonunu döndürür. PS SqlFunctions.StringConvert benim için çalışmadı.


2

"Kişi" genel liste olarak çalışıyorsa, umarım aşağıdaki kod iyi çalışır.

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

Teşekkürler.


2

Bir çözüm daha:

c.ContactId + ""

Sadece boş dize ekleyin ve dize dönüştürülecektir.


Döndürülen Hata: System.NotSupportedException: 'System.Object' yazmak için 'System.Int64' türü döndürülemiyor. LINQ to Entities yalnızca EDM ilkel veya numaralandırma türlerinin dökümünü destekler.
QMaster

1

MySql kullanarak, SqlFunctions.StringConvertbenim için işe yaramadı. SelectListItemProjemde 20'den fazla yerde kullandığım için 20'den fazla LINQ ifadesini değiştirmeden çalışan bir çözüm istedim. Benim çözümüm alt sınıfaSelectedListItem tip dönüşümünü LINQ'dan uzaklaştıran bir tamsayı ayarlayıcı sağlamak geçmekti. Açıkçası, bu çözümün genelleştirilmesi zordur, ancak özel projem için oldukça yardımcı oldu.

Kullanmak için aşağıdaki türü oluşturun ve LINQ sorgunuz yerine SelectedListItemkullanın ve Değer yerine IntValue kullanın.

public class BtoSelectedListItem : SelectListItem
{
    public int IntValue
    {
        get { return string.IsNullOrEmpty(Value) ? 0 : int.Parse(Value); }
        set { Value = value.ToString(); }
    }
}

1

varlık çerçevesini kullanıyorsanız ve tek int'i kabul edilebilir yapmak istiyorsanız, bunu linq sorgusunda kullanabilirsiniz.

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

(int) kullanmak değerinizi int değerine dönüştürür, böylece dize int için herhangi bir dönüştürmeye ihtiyacınız olmaz ve istediğiniz sonucu elde edersiniz.

bu benim projemde benim için çalıştı sanırım bu sizin için yararlı olacaktır


-2

Anladığım kadarıyla, modelinizi "genişletmek" için kısmi bir sınıf oluşturmanız ve sınıfın geri kalan özelliklerinden yararlanabilecek salt okunur bir özellik eklemeniz gerektiğidir.

public partial class Contact{

   public string ContactIdString
   {
      get{ 
            return this.ContactId.ToString();
      }
   } 
}

Sonra

var items = from c in contacts
select new ListItem
{
    Value = c.ContactIdString, 
    Text = c.Name
};

Hayır, LINQ to Entities'de (.NET 3.5'te) özel özellikleri kullanamazsınız.
Craig Stuntz

1
Test etmedim, ama işe yaramayacak. çünkü bu bir tablo alanı özelliği değildir. Önce ToArray () sonra nesneler üzerinde linqing ile yapabilirdi ama DB sorgulamak istiyorum. Bunu yapamayacağımı düşünüyorum. Bir int alanı alan kendi ListItem oluşturdum. Bu benim için daha iyi.
Shimmy Weitzhandler

-2
var items = from c in contacts
select new ListItem
{
    Value = String.Concat(c.ContactId), //This Works in Linq to Entity!
    Text = c.Name
};

onu buldum SqlFunctions.StringConvert((double)c.Age) benim için işe yaramadığını ya da alan tipiNullable<Int32>

Son birkaç gün süren deneme yanılma yöntemini bulabilmek için bana çok şey kattı.

Umarım bu birkaç kodlayıcıya yardımcı olur.


1
Benim için çalışmıyor. " ... System.String Concat(System.Object)bir mağaza ifadesine çevrilemez ... " istisnasını atar .
Slauma

1
Benim için de çalışmıyor. Ayrıca "System.NotSupportedException: LINQ to Entities 'System.String Concat (System.Object)' yöntemini tanımıyor ve bu yöntem bir mağaza ifadesine çevrilemiyor."
camainc

1
ÇALIŞMIYOR - BU CEVABI AÇIN [NotSupportedException: LINQ to Entities, 'System.String Concat (System.Object)' yöntemini tanımıyor ve bu yöntem bir mağaza ifadesine çevrilemiyor.]
Philipp Munin

-6

Deneyebilir misin:

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

Yukarıdaki kod, "LINQ to Entities 'yöntemini' System.String ToString (Int32) 'yöntemini tanımıyor ve bu yöntem bir mağaza ifadesine çevrilemiyor" şeklinde bir hata atacağından çalışmaz.
GK
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.