MVC3 Webアプリケーション内でエラーを取得しています。 LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
クエリからEFを使用して値を取得しようとすると:
public class DataRepository
{
public mydataEntities1 dbContext = new mydataEntities1();
public List<SelectListItem> GetPricingSecurityID()
{
var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
select new SelectListItem
{
Text = m.PricingSecurityID.ToString(),
Value = m.PricingSecurityID.ToString()
});
return pricingSecurityID.ToList();
}
}
これはSQLに変換できません。理論上は可能ですが、実装されていません。
結果が得られたら、投影を実行するだけです。
var pricingSecurityID = (from m in dbContext.Reporting_DailyNAV_Pricing
select m.PricingSecurityID).AsEnumerable()
.Select(x => new SelectListItem{ Text = x.ToString(), Value = x.ToString() });
すでに文字列である場合、最初にToString
を呼び出すのはなぜですか?翻訳は無意味なので、LINQ to Entitiesに含まれていなかったと思います。選択句を次のように変更します。
select new SelectListItem
{
Text = m.PricingSecurityID,
Value = m.PricingSecurityID
}
本当に LINQ to Entitiesでサポートされていないことを行う必要がある場合は、AsEnumerable
を使用してデータベースクエリからインプロセスに移行します。
public List<SelectListItem> GetPricingSecurityID()
{
return dbContext.Reporting_DailyNAV_Pricing
.Select(m => m.PricingSecurityID)
.AsEnumerable() // Rest of query is local
// Add calls to ToString() if you really need them...
.Select(id => new SelectListItem { Text = id, Value = id })
.ToList();
}
ところで、私もジェイソンの異議に同意します。他の場所でレンダリングされるList<string>
を返す方が良いでしょう。
また、just単一のselect
句またはwhere
句のみを使用する場合、クエリ式は実際にはあまり追加しないことに注意してください-LINQの呼び出し特に、クエリ式でare n'tがサポートされているメソッド(ToList
など)を呼び出したい場合は、拡張メソッドをすっきりさせることができます。
これはどう。この例では、dbのVDNフィールドとSkillフィールドの両方が整数です。両方のフィールドからの一致を探しているので、2つの比較があります。
これを含める:
using System.Data.Objects.SqlClient; // needed to convert numbers to strings for linq
数値を比較するときは次のようにします。
// Search Code
if (!String.IsNullOrEmpty(searchString))
{
depts = depts.Where(d => SqlFunctions.StringConvert((double)d.VDN).Contains(searchString.ToUpper())
|| SqlFunctions.StringConvert((double)d.Skill).Contains(searchString.ToUpper()));
}
// End Search Code
Workie。
SQLに変換しようとしているため、変換できないためです。 ToString
への呼び出しを中止し、呼び出し元に戻る前に投影を行います。したがって、select
句を次のように置き換えます
select m.PricingSecurityID
そして言う
return pricingSecurityID
.AsEnumerable()
.Select(x => x.ToString())
.Select(x => new SelectListItem { Text = x, Value = x })
.ToList();
また、UIの懸念とデータクエリの懸念が混在していることに注意してください。これは一般的に悪い習慣です。実際には、IDのリストを返すだけで、コードのUI部分が正しい形式に改ざんされるのを心配する必要があります。
悲しいことに、EFは.ToString()の変換方法を認識していません。埋め込み関数SqlFunctions.StringConvertを使用する必要があります: http://msdn.Microsoft.com/en-us/library/dd466292.aspx また、intにはオーバーロードがないため、型キャストを2倍にする必要があります:-(
var vendors =
from v in Vendors
select new
{
Code = SqlFunctions.StringConvert((double)v.VendorId)
};
私はこの質問に答えていることを理解しており、AsEnumerable()
を使用することが道であることに同意します。ただし、このエラーを解決するためにAsEnumerable()
が非効率的に使用される場合によく遭遇する一般的なシナリオを強調したいと思います。
AsEnumerable()演算子は、ToList()やToArray()とは異なり、クエリを実行しません。まだ延期されています。 AsEnumerable()演算子は、クエリの静的な型付けを変更するだけで、IQueryableをIEnumerableに変換し、コンパイラがクエリの残りをローカルで実行されたものとして扱うようにします。
参考文献
非効率な方法
IEnumerable<InvoiceDTO> inefficientEnumerable =
(from a in db.Invoices
where a.Practice_Key == practiceKey.FirstOrDefault()
select a
).AsEnumerable().
Select(x => new InvoiceDTO
{
InvoiceID = x.InvoiceID,
PracticeShortName = x.Dim_Practice.Short_Name,
InvoiceDate = x.InvoiceDate,
InvoiceTotal = x.InvoiceAmount,
IsApproved = x.IsApproved,
InvoiceStatus = (
x.IsApproved == null ? "Pending" :
x.IsApproved == true ? "Approved" :
x.IsApproved == false ? "Rejected" : "Unknown"
),
InvoicePeriodStartDateText = x.InvoicePeriodStart.ToShortDateString(),
InvoicePeriodEndDateText = x.InvoicePeriodEnd.ToShortDateString(),
InvoicePeriodStartDate = x.InvoicePeriodStart,
InvoicePeriodEndDate = x.InvoicePeriodEnd
}
);
invoices = inefficientEnumerable.ToList();
ここでは、AsEnumerable
がテーブル全体に使用されます。必要ではありませんが、すべての列が選択されています。
より良い方法
IQueryable<InvoiceDTO> invoicesQuery =
(from a in db.Invoices
where a.Practice_Key == practiceKey.FirstOrDefault()
select new InvoiceDTO
{
InvoiceID = a.InvoiceID,
PracticeShortName = a.Dim_Practice.Short_Name,
InvoiceDate = a.InvoiceDate,
InvoiceTotal = a.InvoiceAmount,
IsApproved = a.IsApproved,
InvoiceStatus = (
a.IsApproved == null ? "Pending" :
a.IsApproved == true ? "Approved" :
a.IsApproved == false ? "Rejected" :"Unknown"
),
InvoicePeriodStartDate = a.InvoicePeriodStart,
InvoicePeriodEndDate = a.InvoicePeriodEnd
});
IEnumerable<InvoiceDTO> betterEnumerable = invoicesQuery.AsEnumerable().
Select(x => new InvoiceDTO
{
InvoiceID = x.InvoiceID,
PracticeShortName = x.PracticeShortName,
InvoiceDate = x.InvoiceDate,
InvoiceTotal = x.InvoiceTotal,
IsApproved = x.IsApproved,
InvoiceStatus = x.InvoiceStatus,
InvoicePeriodStartDateText = x.InvoicePeriodStartDate.ToShortDateString(),
InvoicePeriodEndDateText = x.InvoicePeriodEndDate.ToShortDateString(),
InvoicePeriodStartDate = x.InvoicePeriodStartDate,
InvoicePeriodEndDate = x.InvoicePeriodEndDate
}
);
VB.NETを使用してこれを試してください。重要な点は、回答で説明されているように、AsEnumerableの結果を取得する必要があることです。
Dim _EventsDaysResult = From ED In TAdbContext.EventPolicies.AsEnumerable
Where ED.EventID = EID
Select New With {ED.EventID,
.DayInfo =
ED.EventDay.GetValueOrDefault.ToShortDateString & " ( " & ED.EventDayTitle & " ) "}