Argumen DbArithmeticExpression harus memiliki tipe umum numerik

120
TimeSpan time24 = new TimeSpan(24, 0, 0);
TimeSpan time18 = new TimeSpan(18, 0, 0);    

// first get today's sleeping hours
List<Model.Sleep> sleeps = context.Sleeps.Where(
    o => (clientDateTime - o.ClientDateTimeStamp < time24) && 
          o.ClientDateTimeStamp.TimeOfDay > time18 && 
          clientDateTime.TimeOfDay < time18 && 
          o.UserID == userid).ToList(); 

Ekspresi Linq ini memunculkan pengecualian ini:

DbArithmeticExpression arguments must have a numeric common type.

Tolong bantu!

Nawaz Dhandala
sumber
Apa hasil dari clientDateTime - o.ClientDateTimeStamp?
shahkalpesh
noramlly yang harus menjadi objek dari TimeSpan, dalam pengecualian EF dilemparkan.
Nawaz Dhandala

Jawaban:

247

Aritmatika dengan DateTimetidak didukung di Entity Framework 6 dan sebelumnya. Anda harus menggunakan DbFunctions *. Jadi, untuk bagian pertama dari pernyataan Anda, seperti:

var sleeps = context.Sleeps(o =>
    DbFunctions.DiffHours(o.ClientDateTimeStamp, clientDateTime) < 24);

Perhatikan bahwa DiffHoursmetode menerima Nullable<DateTime>.

Inti Entity Framwork (bila digunakan dengan Sql Server, mungkin penyedia db lain) mendukung AddXxxfungsi DateTime (seperti AddHours). Mereka diterjemahkan ke DATEADDdalam SQL.

* EntityFunctionssebelum Entity Framework versi 6.

Gert Arnold
sumber
2

Saya tahu bahwa ini adalah pertanyaan lama tetapi dalam kasus khusus Anda alih-alih menggunakan DBFunctions seperti yang disarankan oleh @GertArnold, tidak bisakah Anda membalikkan operasi, memindahkan aritmatika yang dimaksud dari Lambda?

Toh clientDateTimedan time24merupakan nilai fix sehingga perbedaannya tidak perlu dihitung ulang di setiap iterasi.

Suka:

TimeSpan time24 = new TimeSpan(24, 0, 0);
TimeSpan time18 = new TimeSpan(18, 0, 0);    

var clientdtminus24 = clientDateTime - time24;

// first get today's sleeping hours
List<Model.Sleep> sleeps = context.Sleeps.Where(
    o => (clientdtminus24 < o.ClientDateTimeStamp) && 
          o.ClientDateTimeStamp.TimeOfDay > time18 && 
          clientDateTime.TimeOfDay < time18 && 
          o.UserID == userid).ToList();

Refactor ini biasanya dapat dilakukan jika Anda mencoba membandingkan datetime yang disimpan yang digeser oleh stempel waktu tetap dengan datetime lainnya.

SoonDead
sumber
Saya mengalami situasi yang persis seperti ini, dan ini membantu. Namun, cakupan solusi ini sangat terbatas pada jenis masalah tertentu.
Zimano
@Zimano Ini memecahkan masalah OP tanpa mengharuskannya mengubah teknologi atau menggunakan peretasan. Jika bisa direfraktor seperti ini maka lakukan, jika tidak lakukan seperti dalam jawaban yang diterima.
SoonDead
1

Sebaliknya, jika kinerja bukanlah tujuan yang sebenarnya, Anda dapat mencoba menggunakan AsEnumerable(). Jadi, akan seperti itu

List<Model.Sleep> sleeps = context.Sleeps.AsEnumerable().Where(....

Menambahkan AsEnumerable () akan mengonversi kueri SQL menjadi entitas dan memungkinkan untuk menjalankan fungsi .Net pada kueri tersebut. Untuk info lebih lanjut, lihat di sini tentang AsEnumerable

kacau
sumber