Queryable WHERE String, Int, DateTime o'z ichiga oladi

Men ushbu kod satrini ishlayapman:

query = query.Where(p => 
  p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
  p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
  p.Description.ToString().Contains(globalSearch.ToString()) || 
  p.CheckAmount.ToString().Contains(globalSearch) || 
  p.ClearedDate.ToString().Contains(globalSearch.ToString()) || 
  p.SentDate.ToString().Contains(globalSearch.ToString()));

Bu kod satriga asosan, qo'ng'iroq qilyapman, globalSearch string va BankAccount kabi ustun va < globalSearch bo'lsa Int yoki DateTime bo'lsa (-2233 ClearedDate (DateTime) , SentDate (DateTime) ustunlari uchun CheckAmount (int) va globalSearch ChckNumber ishlamoqda int bilan mos tushsa!

Men noto'g'ri ish qilyapmanmi?

SQL Serverda bu so'rovni bajaraman:

SELECT CONVERT(VARCHAR(MAX), ClearedDate) FROM myTable

va mening barcha sanalarimni qaytarib olish 9-sentyabr 2017 Agar globalSearch 10-sentabr, 2017 bo'lsa, u ishlaydi, ammo u mening kerakli formatda ishlamaydi: 9/9/2017

4
Iltimos, so'rovlar sql profiler yordamida nima qilishini tekshiring. bu sizning linqingizni qanday qilib almashtirish haqida fikr beradi. Men ToString() ning ma'lumotni stringga va qanday formatda konvertatsiya qilish bilan bog'liq bo'lganligini taxmin qilaman.
qo'shib qo'ydi muallif Gurpreet, manba
Muammo yuzaga kelganda berilgan globalSearch va CheckAmount / ClearedDate uchun misollar yo'q. Nima bo'lishi mumkinligi haqida tushuntirish etarli emas. Bu savol yangilanishi yoki aks ettirilmasligi kerak.
qo'shib qo'ydi muallif Robert S., manba
Shuning uchun agar foydalanuvchi "2" bo'lsa, har qanday soni yoki sana maydoni 2 (112 yoki 01/03/2017 sana kabi) o'z ichiga olgan barcha elementlarni qaytarishni xohlaysiz. Juda foydali emas.
qo'shib qo'ydi muallif Evk, manba
ToString formatida foydalanishga harakat qildingizmi? Misol: p.ClearedDate.ToString ("MM/dd/yyyy")
qo'shib qo'ydi muallif erikscandola, manba
kodingizni qadam-qadam disk raskadrovka qilishga urinib ko'ring, 1- "Tostring" usulining kirish ma'lumotingizga to'g'ri ishlayotganligini tekshirib ko'ring. 2-sql-server ma'lumotlar bazasida sana vaqti formatini sana vaqt kiritishingiz bilan mosligini tekshirib ko'ring
qo'shib qo'ydi muallif daren shan, manba
Xurmodagi mantiq nima? Haqiqiy sana mos kelishini xohlaysizmi?
qo'shib qo'ydi muallif AndersJH, manba

7 javoblar

Agar globalSearch bir Int mavjud bo'lsa, unchalik ahamiyatga ega emasligingiz kerak, chunki siz uni har doim bir mag'lubiyatga aylantirasiz, agar DATETIME bo'lmasa va siz ustunlarni har doim satrlarga o'tkazib turadigan bo'lsangiz, unda bir ustun varchar yoki Int bo'ladi.

Eslatib o'tamizki, sharhlaringiz asosida siz faqat oy, kun va yilni taqqoslayotganingizni va ClearedDate

Kodingiz bilan uchta mumkin muammolarni ko'rib turibman:

  1. GlobalSearch so'zi, CheckAmount
  2. uchun mag'lubiyatga aylantirilmaydi
  3. Siz chaqiruvdan oldin ustunlaringizning hech biriga null yo'qligini tekshirmaysiz .ToString, ehtimol sizning ustunlaringiz Nullsga ruxsat bermaydi
  4. Sizning kodingiz juda oson o'qilmaydi, chunki u odamlarning qarama-qarshiliklarini aniqlaydi.

GlobalSearch-ni mag'lubiyatga bir marta va har safar o'zgartiradigan yana o'qiladigan kod, chunki yana ham globalAgarani CheckAmount uchun mag'lubiyatga aylantirmaysiz:

var gsStr = globalSearch.ToString();
var gsDate = DateTime.MinDate;
if(globalSearch.GetType() == typeof(DateTime))
{
    gsDate = globalSearch;
}
query = query.Where(p => p.ChckNumber.ToString().Contains(gsStr) 
|| p.BankAccount.ToString().Contains(gsStr) 
|| p.Description.ToString().Contains(gsStr) 
|| p.CheckAmount.ToString().Contains(gsStr) 
|| p.ClearedDate.Date == gsDate.Date
|| p.SentDate.ToString().Contains(gsStr));

Agar siz C# 6.0 dan foydalanayotgan bo'lsangiz, sizning ustunlaringiz hozirda yoki kelajakda nulllarga ruxsat beradigan bo'lsa, sizdan yangi Null tarqalishi operatoridan foydalanishingiz mumkin:

var gsStr = globalSearch.ToString();
var gsDate = DateTime.MinDate;
if(globalSearch.GetType() == typeof(DateTime))
{
    gsDate = globalSearch;
}
query = query.Where(p => p.ChckNumber?.ToString().Contains(gsStr) 
|| p.BankAccount?.ToString().Contains(gsStr) 
|| p.Description?.ToString().Contains(gsStr) 
|| p.CheckAmount?.ToString().Contains(gsStr) 
|| p.ClearedDate?.Date == gsDate.Date
|| p.SentDate?.ToString().Contains(gsStr));

CheckAmount uchun globalSearch ToStringni aylantirishi Sizda muammolarni bartaraf qilish, kodingizni yanada o'qib chiqish va nulllardan himoya qilish xatolarni tuzatmasa, disk raskadrovka qilishni osonlashtiradi.

7
qo'shib qo'ydi
Ushbu so'rovni SQL Serverda tanlash CONVERT (VARCHAR (MAX), ClearedDate) dan myTable va mening barcha kunlari qaytaringing Sentyabr 9, 2017 GlobalSearch Sentyabr 10, 2017 bo'lsa, u ishlaydi, lekin u menga kerakli formatda ishlamaydi 9/9/2017
qo'shib qo'ydi muallif user979331, manba
@ user979331 DATETime.Dates bilan solishtirish uchun javobni yangiladim
qo'shib qo'ydi muallif Brian Ogden, manba
Savolga sql yorlig'i bor, shuning uchun ehtimol ishlatiladigan Entity Framework mavjud va agar shunday bo'lsa, kod bilan .ToString() bu erda ishlashi mumkin emas.
qo'shib qo'ydi muallif Marcin Zablocki, manba
@ user979331 Javob yaxshi, uni sinab ko'ring. Bundan tashqari, siz CONVERT kunlarini foydalanganda siz kerakli formatga parametr sifatida kiritishingiz kerak, bu yerda alo = lanadi w3schools.com /sql/func_convert.asp
qo'shib qo'ydi muallif jambonick, manba

Kodingiz so'rovdagi birinchi maydon so'rovlar atamasiga mos keladigan qatorlarni qaytaradi. Bu haqiqat kerakmi? Men taklif qilmayman. So'rovlar muddati ma'lum bo'lgan aniq maydon uchun mo'ljallangan bo'lishi kerak.

Sizda so'rovlar atamasini maydon tarkibidagi substring sifatida topishga qiziqasizmi? Hech bo'lmasa, tamsayı va sana dalalariga nisbatan, sizning so'rovlaringiz muddati o'z ichiga olishi mumkin bo'lgan qiymatlarni bildirmaganingizdek bo'lsa ham, ehtimol unchalik to'g'ri kelmaydi.

Varchar maydonlarini .ToString() ga o'zgartirmoq kerak emas. Xuddi shunday, agar DateTime yoki Integer maydonlarini so'rovlaringiz paytida siz tegishli turdagi so'rovlar atamasini taqdim qilsangiz, siz ularni o'zgartirmoqchisiz (aslida, substring uchun). Bu null maydon qiymatlari bilan bog'liq muammolarni bartaraf qiladi va ortiqcha qayta ishlashni olib tashlaydi.

Sizning so'rovingizni ushbu fikrlarni eslatib turishingiz mumkin. So'rovlar ob'ektini "bir o'lchamga mos" ishlatish o'rniga, siz ko'proq qasddan yondoshishingizni tavsiya qilaman.

Misol uchun, har bir so'rovlar maydoni uchun nullable xususiyatini o'z ichiga olgan so'rovlar obyekti yaratishingiz mumkin.

public partial class AccountQuery
{
    public string CheckNumber { get; set; }
    public string BankAccount { get; set; }
    public string Description { get; set; }
    public int? CheckAmount { get; set; }
    public DateTime? ClearedDate { get; set; }
    public DateTime? SentDate { get; set; }
}

So'rovlar mantig'ini qamrab olish uchun sizning modeniz/DTO ga usulni qo'shing. AccountQuery ob'ektini qabul qiladi va undagi nol bo'lmagan xususiyatlarga mos keladigan ob'ekt xususiyati bilan mos keladi.

public class Account
{
    public string CheckNumber { get; set; }
    public string BankAccount { get; set; }
    public string Description { get; set; }
    public int CheckAmount { get; set; }
    public DateTime ClearedDate { get; set; }
    public DateTime SentDate { get; set; }
    public bool Matches(AccountQuery query)
    {
        return (!string.IsNullOrEmpty(query.CheckNumber) && query.CheckNumber == CheckNumber) ||
               (!string.IsNullOrEmpty(query.BankAccount) && query.BankAccount == BankAccount) ||
               (!string.IsNullOrEmpty(query.Description) && query.Description == Description) ||
               (query.ClearedDate.HasValue && query.ClearedDate == ClearedDate) ||
               (query.SentDate.HasValue && query.SentDate == SentDate) ||
               (query.CheckAmount.HasValue && query.CheckAmount == CheckAmount);
    }
}

Sizning so'rovingiz keyin, masalan:

var aq = new AccountQuery
{
    ClearedDate = DateTime.Today
};
query.Where(p => p.Matches(aq));

Ushbu so'rovning mantiqiyligi asl kodingiz bilan bir xil emasligiga e'tibor bering, yuqorida ta'kidlaganimdek, aniq ko'rinmaydi.

2
qo'shib qo'ydi

Kech javob uchun uzr

ToStringni Numerics uchun ishlatmang

Buning o'rniga globalsearch String NUmeric yoki yo'qligini tekshiring,

agar u soni bo'lsa, uni to'liq yoki er-xotin kabi kerakli maydonga aylantiring. Va DATETime haqida bo'lgani kabi,

Sana formatlashtiruvchisidan p.ClearedDate.ToString ("dd/mm/yyyy") sifatida foydalaning va globalsearchni formatlash uchun kerakli formatda bo'lishi shart emas

mening halim bu bo'lishi mumkin,

query = query.Where(p => p.ChckNumber==int.TryParse(globalSearch.ToString, out num)?num:globalSearch.ToString(); || p.BankAccount.ToString().Contains(globalSearch.ToString()) || p.Description.ToString().Contains(globalSearch.ToString()) || p.CheckAmount==decimal.TryParse(globalSearch.ToString, out num)?num:globalSearch.ToString(); || p.ClearedDate.ToString("dd/MM/yyyy").Contains(globalSearch.ToString()) || p.SentDate.ToString("dd/MM/yyyy").Contains(globalSearch.ToString()));

2
qo'shib qo'ydi

Sana qismini formatlashni harakat qilib ko'ring

 p.ClearedDate.ToString("dd/MM/yyyy").Contains(globalSearch.ToString("dd/MM/yyyy"))

Bundan tashqari, ling Pad yoki shunga o'xshash vositani yoki ling yordamchisining kengaytmasini sinab ko'rishingiz mumkin

1
qo'shib qo'ydi
Nima uchun bu erda o'z ichiga olgan foydalanasiz? Bunday tarixiy satr hech qachon o'zidan boshqa tarix qatorini o'z ichiga olmaydi va bu holda unga teng. Shunday qilib, tenglik uchun sinov shu erda va tezroq bo'lishi mumkin.
qo'shib qo'ydi muallif Robert S., manba
Buning o'rniga siz bilan kelishib olsam, yana bir usulni qo'llang. Dastlabki holatdan kamroq tekshirilsin (agar imkon bo'lsa). Ushbu yondashuv har doim ham men uchun ishlaydi, hatto formatda bir oz farq (03/03/2017 yoki 3/3/2017)
qo'shib qo'ydi muallif Saurabh, manba

Sizning talabingizga muvofiq formatni ishlatishingiz kerak. Raqamlar bo'yicha kodlangan barcha sana formati.

For instance, 110 -> mm-dd-yyyy

 SELECT CONVERT(VARCHAR(MAX), ClearedDate, 110) FROM myTable
1
qo'shib qo'ydi

Salom, sizning sana to'g'ri formatini qidirayotgan bo'lsangiz, buni sinab ko'ring.

SELECT CONVERT(VARCHAR(10), SYSDATETIME(), 103)
1
qo'shib qo'ydi

Bir martalik sana fYoKImati. ToString uchun oldindan belgilangan fYoKImatni belgilash uchun argument sifatida char ishlatishimiz mumkin. Ular standart fYoKImatlardir.

query = query.Where(p => 
p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
p.Description.ToString().Contains(globalSearch.ToString()) || 
p.CheckAmount.ToString().Contains(globalSearch) || 
p.ClearedDate.ToString("d").Contains(globalSearch.ToString()) || 
p.SentDate.ToString("d").Contains(globalSearch.ToString()));

YoKI

ToShYoKItDateString() is equivalent to the lower case d ToString("d")

query = query.Where(p => 
p.ChckNumber.ToString().Contains(globalSearch.ToString()) || 
p.BankAccount.ToString().Contains(globalSearch.ToString()) || 
p.Description.ToString().Contains(globalSearch.ToString()) || 
p.CheckAmount.ToString().Contains(globalSearch) || 
p.ClearedDate.ToShYoKItDateString().Contains(globalSearch.ToString()) || 
p.SentDate.ToShYoKItDateString().Contains(globalSearch.ToString()));
1
qo'shib qo'ydi