Linqからエンティティへの整数から文字列への変換に関する問題


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、コードはSQLに変換されるため、ELINQ(linq 2エンティティ)に問題があります。内部のToStringリクエストに関しては、「ToString」をSQLに変換する方法がわかりません。linq 2オブジェクトとは異なり、変換がなく、すべてがCLRラムダの場合、要求されたオブジェクトに対して直接実行されます。
Shimmy Weitzhandler 2010

1
私はそれらがその種のエラーをコンパイルすることを許していること、そして原因の明白な英語の説明を見つけるために永遠にトローリングしなければならなかったことにイライラしている(sans legal-eseとacademia-ese)。
StingyJack 2010

1
あなたしている権利を、彼らはまた、右、彼らは特にないToStringメソッドについてEFの非常に初期のバージョン:)で、SQLにCLRおよびカスタマイズされたCLRの機能すべてを翻訳することになっていないしている、ブライアンの答えを読む:のstackoverflowを。 com / questions / 1066760 /…
Shimmy Weitzhandler

すばらしいですが、3.5ではなく4を使用している人はどうですか?じゃあ何?
エカテリーナ

回答:


313

EF v4で使用できますSqlFunctions.StringConvert。intにはオーバーロードがないため、doubleまたはdecimalにキャストする必要があります。コードは次のようになります。

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で機能しないようですTypw 'System.Data.Objects.SqlClient.SqlFunctions'のMethode 'System.String StringConvert(System.Nullable`1 [System.Double])'がeinen Speicherausdruck 「LINQ to Entities」のübersetztwerden。( "LINQ to Entities"には翻訳できません)
OneWorld 2013年

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

これはそれを解決する1つの方法ですが、これにより実行時間が長くなることに注意してください。大量のオブジェクトがある場合、このforeach
はやり

9

LinqToObject:連絡先を使用します。AsEnumerable()

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

ありがとう。ちなみに、私は少し異なる問題を解決しようとしています。私はエンティティ/ラムダにLINQを使用していますが、これは機能します。IntをStringに変換し、「Contains」を使用して一致する結果を検索しようとしました->つまり、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で文字列を操作します。この例では、Contactのフルネームと2つのInteger列(ContactIDとLocationID)の文字列連結であるContactLocationKeyを含むデータのセットを取得します。

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

さて、2つの匿名のselectを記述する必要があることは面倒になることを認めますが、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

はい、すでに使用しています。MVC3、EF4、CTP5、SQL CE4で動作します。
Nestor、

これは、ボクシングを2倍にしてStringConvertを使用するよりもエレガントに見えます。
CmdrTallen

9
ただし、この場合はデータベースからすべてのデータをフェッチし、このリストをフィルタリングする前にreturn list.ToList();!!
Wahid Bitar 2011

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

ブライアン・コートンの答えは素晴らしいです!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

もう1つの解決策:

c.ContactId + ""

空の文字列を追加するだけで、文字列に変換されます。


返されたエラー:System.NotSupportedException:タイプ 'System.Int64'をタイプ 'System.Object'にキャストできません。LINQ to Entitiesは、EDMプリミティブまたは列挙型のキャストのみをサポートしています。
2018

1

MySqlを使用SqlFunctions.StringConvertして、私のために動作しませんでした。SelectListItem私はプロジェクトの20以上の場所で使用しているため、20以上のLINQステートメントを歪めずに機能するソリューションが必要でした。私の解決策はSelectedListItem、型変換をLINQから遠ざける整数セッターを提供するためにサブクラス化することでした。明らかに、この解決策を一般化することは困難ですが、私の特定のプロジェクトには非常に役立ちました。

使用するには、次のタイプを作成し、LINQクエリでの代わりにSelectedListItem使用し、Valueの代わりにIntValue を使用します。

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)ではカスタムプロパティを使用できません。
Craig Stuntz、2009

1
テストはしませんでしたが、動作しません。これはテーブルフィールドプロパティではないためです。最初にToArray()でそれを実行し、次にオブジェクトをlinqingすることができますが、DBにクエリを実行します。できないと思います。intフィールドを取る独自のListItemを作成しました。それは私にとってはうまくいきます。
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

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.