How to get all the records between two dates, below is my code. Can anyone help me out?
var query = from l in _DbContext.Licenses
join lp in _DbContext.LicenseParts on l.PartNumber equals lp.PartNumber
join p in _DbContext.Products on lp.ProductId equals p.Id
join lsn in _DbContext.LicenseSerialNumbers on l.Id equals lsn.LicenseId
join lact in _DbContext.LicenseActivations on lsn.Id equals lact.LicenseSerialNumberId
join bpsn in _DbContext.BasePartSerialNumbers on JsonExtensions.JsonValue(lact.ActivationInfoJSON, "$.SerialNumber") equals bpsn.SerialNumber into bpsnOuter
from bpsnO in bpsnOuter.DefaultIfEmpty()
join bp in _DbContext.BaseParts on bpsnO.BasePartId equals bp.Id into bpOuter
from bpO in bpOuter.DefaultIfEmpty()
join lpc in _DbContext.LicensePartConfigurations on
new
{
Key1 = lp.Id,
Key2 = JsonExtensions.JsonValue(lact.ActivationInfoJSON, "$.Version")
}
equals
new
{
Key1 = lpc.LicensePartId,
Key2 = lpc.Version
}
into lpcOuter
from lpcO in lpcOuter.DefaultIfEmpty()
where lp.Active == true && lact.Status == Common.LicenseActivationStatus.ACTIVE
select new ActivatedLicenseQueryInfo
{
p = p,
lact = lact,
version = lpcO == null ? "" : lpcO.Version,
bPart = bpO == null ? "" : bpO.PartNumber,
};
availableOrderRequest.Products = Array.ConvertAll(availableOrderRequest.Products, x => x.ToUpper());
query = query.Where(o => availableOrderRequest.Products.Contains(o.p.Name.ToUpper()));
query = query.Where(o => o.l.CreatedAt >= Convert.ToDateTime(availableOrderRequest.DateRangeFrom) && o.l.CreatedAt <= Convert.ToDateTime(availableOrderRequest.DateRangeTo));
In DB CreatedAt column date's like 2010-09-10 10:17:28.8133333 formate, and input DateRangeFrom and DateRangeTo inputs like "2021-04-01" but I am getting an error:
the problem is this line
query = query.Where(o => o.l.CreatedAt >= Convert.ToDateTime(availableOrderRequest.DateRangeFrom) && o.l.CreatedAt <= Convert.ToDateTime(availableOrderRequest.DateRangeTo));
without this line it's working fine, if I add this line I am getting the below error
Message [string]:"The LINQ expression 'DbSet\n.Join(\n outer: DbSet, \n inner: l => l.PartNumber, \n outerKeySelector: l0 => l0.PartNumber, \n innerKeySelector: (l, l0) => new TransparentIdentifier<License, LicensePart>(\n Outer = l, \n Inner = l0\n ))\n.Join(\n outer: DbSet, \n inner: ti => ti.Inner.ProductId, \n outerKeySelector: p => p.Id, \n innerKeySelector: (ti, p) => new TransparentIdentifier<TransparentIdentifier<License, LicensePart>, Product>(\n Outer = ti, \n Inner = p\n ))\n.Join(\n outer: DbSet, \n inner: ti0 => ti0.Outer.Outer.Id, \n outerKeySelector: l1 => l1.LicenseId, \n innerKeySelector: (ti0, l1) => new TransparentIdentifier<TransparentIdentifier<TransparentIdentifier<License, LicensePart>, Product>, LicenseSerialNumber>(\n Outer = ti0, \n Inner = l1\n ))\n.Join(\n...
Although an IQueryable<...>
looks similar to an IEnumerable<...>
, there is a major difference.
Both objects reprresent an enumerable sequence of similar object. An object that implements IEnumerable, is supposed to be enumerated by your local process. It holds everything to get the first element of the sequence, and if you've got an element, it can get the next element of the sequence as long as there is a next element.
At low level, enumerating the sequence is done as follows:
IEnumerable<Product> products = ...
using (IEnumerator<Product> productEnumerator = products.GetEnumerator())
{
while (productEnumerator.MoveNext())
{
Product product = productEnumerator.Current;
this.Process(product);
}
}
Whenever you use foreach, then deep down these statements are executed. The LINQ methods that do not return IEnumerable<...>
, like ToList, FirstOrDefault, Count, Any, etc, will also deep inside call GetEnumerator / MoveNext / Current
Although an object that implements IQueryable also represents an enumerable sequence of similar objects, it is a bit different. The IQueryable holds an Expression
and a Provider
. The Expression represents the data that must be fetched. The Provider knows which process will provide the data (usually a database management system), and what language is used to communicate with this DBMS (usually SQL).
If you call IQueryable.GetEnumerator
, the Expression is sent to the Provider, who will translate it into SQL and execute the request at the DBMS. The fetched data is represented as an IEnumerator<...>
to the caller, who can repeatedly call MoveNext / Current, to enumerate the fetched data.
Some Providers are smart, and will delay fetching the data until the first MoveNext. Others are even smarter: they will not fetch all data at once, but "per page", of say, the first 25 elements. If you only enumerate the first few elements (like FirstOrDefault), then not all data is fetched for nothing. After these 25 elements are enumerated, the next page is fetched.
The problem is, that your Provider does not know how to translate Convert.ToDateTime(...)
into SQL. In fact, there are even several LINQ methods that are not supported by your Provider. See List of Supported and Usupported LINQ methods .
Although you didn't say so, it seems to me that object availableOrderRequest
is an object in your local process. This object has at least two (string?) properties DateRangeFrom and DateRangeTo.
My advice would be to let your local process convert these properties to DateTime before you execute the query.
var availableOrderRequest = ...
DateTime dateRangeFrom = Convert.ToDateTime(availableOrderRequest.DateRangeFrom);
DateTime dateRangeTo = Convert.ToDateTime(availableOrderRequest.DateRangeTo);
var query1 = from l in dbContext.Licenses ...
var query2 = query1.Where(o => availableOrderRequest.Products.Contains(o.p.Name.ToUpper()));
var query3 = query2.Where(o => o.l.CreatedAt >= dateRangeFrom && o.l.CreatedAt <= dateRangeTo);
This looks much neater, and is better to read. What is more important, is, that it is also more efficient, as the Convert.ToDateTime(...)
is executed only once, not once per o
in the Where
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.