Saya memiliki metode ekstensi umum berikut:
public static T GetById<T>(this IQueryable<T> collection, Guid id)
where T : IEntity
{
Expression<Func<T, bool>> predicate = e => e.Id == id;
T entity;
// Allow reporting more descriptive error messages.
try
{
entity = collection.SingleOrDefault(predicate);
}
catch (Exception ex)
{
throw new InvalidOperationException(string.Format(
"There was an error retrieving an {0} with id {1}. {2}",
typeof(T).Name, id, ex.Message), ex);
}
if (entity == null)
{
throw new KeyNotFoundException(string.Format(
"{0} with id {1} was not found.",
typeof(T).Name, id));
}
return entity;
}
Sayangnya Entity Framework tidak tahu bagaimana menangani predicate
sejak C # mengonversi predikat menjadi berikut ini:
e => ((IEntity)e).Id == id
Entity Framework menampilkan pengecualian berikut:
Tidak dapat mentransmisikan jenis 'IEntity' untuk mengetik 'SomeEntity'. LINQ ke Entitas hanya mendukung casting EDM primitif atau jenis enumerasi.
Bagaimana kami dapat membuat Entity Framework berfungsi dengan IEntity
antarmuka kami ?
Beberapa penjelasan tambahan tentang
class
"perbaikan".Jawaban ini menunjukkan dua ekspresi yang berbeda, satu dengan dan yang lainnya tanpa
where T: class
batasan. Tanpaclass
kendala kami memiliki:dan dengan kendala:
Kedua ekspresi ini diperlakukan secara berbeda oleh kerangka entitas. Melihat sumber EF 6 , seseorang dapat menemukan bahwa pengecualiannya berasal dari sini, lihat
ValidateAndAdjustCastTypes()
.Apa yang terjadi adalah, bahwa EF mencoba untuk
IEntity
memasukkan sesuatu yang masuk akal di dunia model domain, namun gagal dalam melakukannya, oleh karena itu pengecualian dilemparkan.Ekspresi dengan
class
batasan tidak berisiConvert()
operator, cast tidak dicoba dan semuanya baik-baik saja.Masih menjadi pertanyaan terbuka, mengapa LINQ membangun ekspresi yang berbeda? Saya berharap beberapa penyihir C # bisa menjelaskan hal ini.
sumber
Entity Framework tidak mendukung ini di luar kotak, tetapi kerangka kerja
ExpressionVisitor
yang menerjemahkan ekspresi mudah ditulis:Satu-satunya hal yang harus Anda lakukan adalah mengubah predikat yang diteruskan menggunakan ekspresi pengunjung sebagai berikut:
Pendekatan lain -less flexible- adalah dengan memanfaatkan
DbSet<T>.Find
:sumber
Saya mengalami kesalahan yang sama tetapi masalah yang serupa tetapi berbeda. Saya mencoba membuat fungsi ekstensi yang mengembalikan IQuer dapat tetapi kriteria filter didasarkan pada kelas dasar.
saya akhirnya menemukan solusi yang untuk metode ekstensi saya untuk memanggil. Pilih (e => e sebagai T) di mana T adalah kelas anak dan e adalah kelas dasar.
detail lengkapnya ada di sini: Buat ekstensi <T> IQuerable menggunakan kelas dasar di EF
sumber