On the query below how can remove de time part of the datetime column to get only the distinct dates?
using (var ctx = new DBConn())
{
var q = ctx.Table.Select(r => r.datetimefield).Distinct();
}
You are stumbling over a fault with linq-to-sql or EF (I don't know which one you are using). The straight forward solution would be to use the DateTime.Date property, however, this is unsupported in both ORMs, it doesn't map to an SQL method.
You have two solutions:
eager evaluation of the query by using ToList:
var q = ctx.Table.ToList().Select(r => r.datetimefield.Date).Distinct();
create a field detailing only the date component in the database. This is the way I usually go as you can stay in the database and execute the query there.
Assuming r.datetimefield is a DateTime, you can use DateTime.Date to remove the time component:
var q = ctx.Table.Select(r => r.datetimefield.Date).Distinct();
Related
I am getting the following error:
Only parameterless constructors and initializers are supported in LINQ
to Entities.
I am trying to query data from a result set, and part of the new result set returns a new date field.
var result = debts.Select(x => new
{
x.Snowball.User.Email,
x.SnowballID,
x.Description,
x.ID,
x.DueDayOfMonth,
Due = new DateTime(ExecutionDate.Year,
ExecutionDate.Month,
x.DueDayOfMonth)
}).ToList();
Is there a way I can create this deduced datetime?
I came here looking for the same thing, but on further research found another way using DbFunctions.CreateDateTime in System.Data.Entity. Using this method your query would look like this:
var result = debts.Select(x => new
{
x.Snowball.User.Email,
x.SnowballID,
x.Description,
x.ID,
x.DueDayOfMonth,
Due = DbFunctions.CreateDateTime(ExecutionDate.Year,
ExecutionDate.Month,
x.DueDayOfMonth, 0,0,0)
}).ToList();
EDIT: This is for EF6 and later, for earlier versions of EF use System.Data.Entity.Core.Objects.EntityFunctions instead of DbFunctions
LINQ to Entities has a boundary for the query.
The IQueryable result allows one or more filters and selections etc. to be added step by step if you wish.
While the query is being added to nothing has hit the database yet; only when you access the result set will the query be constructed by the LINQ Provider (a single Transact SQL Query for example), then run on the database, and its result returned.
In the case you have shown, you are trying to create a new object (Date - but could also be one of your own classes) in the database's result set.
So, for each row returned from the database query you are trying to create a column from an object (from your code base) different for each row (need to pass the parameters to the constructor).
Because the underlying provider cannot guarantee to be able to create arbitrary objects from an external source on the fly, this is not allowed (prevented by the LINQ Provider).
The query that will be run against the database is 'debts'. This will return all of the rows from the query unfiltered (as there is no WHERE clause).
The next query will be run in your code. In your code you can use parameterised constructors - and is now LINQ To Objects.
So the way to distinguish the separate stages of the query, and do what you want to do, is to place the ToList() at the end of the query that runs against the database so that the query is generated, run, and the results returned.
Then construct and run your next query (in your code) on those results.
var result = debts.ToList().Select(x => new
{
x.Snowball.User.Email,
x.SnowballID,
x.Description,
x.ID,
x.DueDayOfMonth,
Due = new DateTime(ExecutionDate.Year, ExecutionDate.Month, x.DueDayOfMonth)
});
You could create your own Date class with a parameter-less constructor and set it using property initializer syntax like
Due = new Date(){Year = ExecutionDate.Year, Month = ExecutionDate.Month, Day = x.DueDayOfMonth}
Then just define a cast from Date to DateTime.
You may try this:
var result = debts.Select(x =>
new
{
x.Snowball.User.Email, x.SnowballID, x.Description, x.ID,
x.DueDayOfMonth,
exY = ExecutionDate.Year,
exM = ExecutionDate.Month,
exD = x.DueDayOfMonth)
}).ToList()
.Select(a => new {Email, SnowballID, Description, ID, Due=new DateTime(exY, exM, exD)})
.ToList()
This is my code:
var qry = (from u in _db.ApplicationUsers
select new UserBroadcastDTO()
{
UserId = u.Id,
DateCreated = u.DateCreated
}).OrderByDescending(q => q.DateCreated);
I have this exception:
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression.
How can I convert date format in linq?
Your problem is that formatting doesn't belong in the Linq query itself. The query is concerned with data, not presentation.
Now, if you are trying to project the results of the query into something for display, then make sure you enumerate the collection before doing your formatting. You can call .ToList(), but in most cases, simply adding an .AsEnumerable() will do the trick, drawing a line in the sand between what can be made part of the SQL (or other back-end store) query, and what can't. Then, you add another select to do your projection.
Like this:
var qry = _db.ApplicationUsers
.OrderByDescending(q => q.DateCreated)
.AsEnumerable()
.Select new UserBroadcastDTO
{
UserId = u.Id,
DateCreated = u.DateCreated.ToString("yyyy-MM-dd hh:mm")
});
The .AsEnumerable call can be a .ToList if you want, but .AsEnumerable will work just fine and still defers execution until later if needed, but the important thing is that you're stopping it from being an IQueryable, so anything after that point doesn't try to work its way into the SQL query, and you won't get the error.
This is happening because LINQ to Entities is trying to convert the expression tree into SQL query and .ToString(string) can not be translated into SQL. you should handle the result in your presentation layer for example inside your view in an MVC app:
#Model.DateCreated.ToString("yyyy-MM-dd hh:mm")
ypu need to materialize the query so that can happen in linq to objects linq to entities cannot do that
var qry = _db.ApplicationUsers.OrderByDescending(q => q.DateCreated)
.Select(u => new UserBroadcastDTO {
UserId = u.Id,
DateCreated = u.DateCreated
});
// do your additional logic then materialize the query
var formattedresults = qry.ToList().Select(q => new UserBroadcastDTO {
UserId = q.Id,
DateCreated = q.DateCreated.ToString("yyyy-MM-dd hh:mm")
});
Originally I had this linq statement:
refusedZones = session.Query<ZoneBO>().Where(x => x.StateId == _config.RefusedStateId).ToList();
Works fine and I get my list with business objects. I now need to change this query, I still want my list of strongly typed business objects back, but I have to do a join with another table.
I have tested this SQL query and it works the way I want it to:
select z.ZoneName, z.ZoneSerial from zone z join transactionzone tz on z.ZoneId = tz.ZoneId where z.StateId = 3 and tz.StateId = 16
My question is how do I do this in linq with a Lambda expression? I assume it will start like this...
var refusedZones = session.Query<ZoneBO>().Join(.......expression here....).ToList();
Can anyone help me with the santax please, very new to linq, finding it confusing.
You will need to add a reference from Zone to TransactionZone. How have you setup your mappings?
Once you have a reference setup it is unnecessary to explicitly write the joins in LINQ.
You can do this:
session.Query<ZoneBO>()
.Where(x => x.State.Id == 3 && x.TransactionZone.State.Id == 16)
.ToList()
Problem details:
SQL Server 2005;
Entity Framework 4.0.
I'm trying with linq to run a query for a period of time, only. Exemple:
I have the following datetime data in my server:
30/03/2012 12:53:22
30/03/2012 17:23:29
04/04/2012 11:10:14
04/04/2012 19:06:55
I want to run a query that will return me all data between the time (12:00 and 20:00) and the query have to return to me the following data:
30/03/2012 12:53:22
30/03/2012 17:23:29
04/04/2012 19:06:55
Or between (11:00 and 13:00) and the query have to return to me the following data:
30/03/2012 12:53:22
04/04/2012 11:10:14
How can i do this with linq? Is it possible (to ignore the date, use only the time)?
var filteredTimes = myContext.MyTable
.Where(r => SqlFunctions.DatePart("hour", r.DateField) >= 11 &&
SqlFunctions.DatePart("hour", r.DateField) <= 13);
You need to include System.Data.Objects.SqlClient to get SqlFunctions.
If you convert the date value to a double and use the fractional part of if, you get a number between 0 and 1 that represents a time in a day. Having that, it is trivial to test for time intervals, where e.g. 13:45 would be 0,5729166667 (or more precise: 13:45.345 is 0,572920679).
You can do this because EF (i.e. 4.3, the version I use) translates Cast and even Math functions into SQL:
mycontext.Data.Where(dt => dt.DateTime.HasValue)
.Select(dt => dt.DateTime.Value).Cast<double>()
.Select(d => d - Math.Floor(d))
.Where(... your comparisons
This translates to Sql containing CAST([date column] AS float) and Sql's FLOOR function.
After your comments:
It looked so easy, but I can't find a way to instruct EF to do a CAST on a single property in a Select(). Only the Cast<>() function is translated to CAST (sql), but that operates on a set.
Well, fortunately, there is another way:
mycontext.Data.Where(dt => dt.DateTime.HasValue)
.Select(dt => new
{
Date = DbFunctions.TruncateTime(dt.DateTime.Value),
Ms = DbFunctions.DiffMilliseconds(
DbFunctions.TruncateTime(dt.DateTime.Value), dt.DateTime.Value)
})
.Where(x => x.Ms > lower && x.Ms < upper)
where lower and upper are the TotalMilliseconds property of TimeSpan objects.
Note that this is horribly inefficient in sql! The date functions are repeated for each comparison. So make sure that you do the comparisons on a set of data that has been confined as much as possible by other criteria. It may even be better to fetch data in memory first and then do the comparisons.
Note: prior to EF6, DbFunctions was EntityFunctions.
If you had a date and a time column in your table (as possible with SQL Server 2008), you could do this directly in SQL.
As that's not the case, you have to do it like this:
// the first two lines can be omitted, if your bounds are already timespans
var start = startDate.TimeOfDay;
var end = endDate.TimeOfDay;
var filteredItems = context.Items.ToList()
.Where(x => x.DateTimeColumn.TimeOfDay >= start
&& x.DateTimeColumn.TimeOfDay <= end);
-You can use the TimeOfDay property on the dates to compare them.
string timeAsString = "13:00";
from f in TableRows
where f.Date.TimeOfDay > DateTime.Parse("11-12-2012 "+timeAsString).TimeOfDay
select f
EDIT
here is some code you can test that runs for me:
DateTime d = DateTime.Parse("12-12-2012 13:00");
List<DateTime> dates = new List<DateTime>();
dates.Add(DateTime.Parse("12-12-2012 13:54"));
dates.Add(DateTime.Parse("12-12-2012 12:55"));
dates.Add(DateTime.Parse("12-12-2012 11:34"));
dates.Add(DateTime.Parse("12-12-2012 14:53"));
var result = (from f in dates where f.TimeOfDay > d.TimeOfDay select f);
EDIT 2
Yea it seems that you needed to .ToList(), which, tbh you should have been able to figure out. I had no way of knowing what of collection you had. Not sure either of us deserve a downvote for trying to help you when you don't supply an awful amount of information on the problem
I have a table that has two records (there will be many at runtime). The deviceId of the records are, “DEVICE1” and “DEVICE2”. I want to use a regular expression to extract records.
The code below compiles but fails to return a result. When I hover the cursor on the “devices.ToList()” statement I get the following error:
base {System.SystemException} = {"LINQ to Entities does not recognize the method 'System.Text.RegularExpressions.MatchCollection Matches(System.String)' method, and this method cannot be translated into a store expression."}”
Can anyone show me how I can modify my query so that this would return records based on the expression?
filterText = #"DEVICE.";
Regex searchTerm = new Regex(filterText);
using (var ctx = new MyEntities())
{
var devices = from d in ctx.Devices
let matches = searchTerm.Matches(d.DeviceId)
where matches.Count > 0
select ((Device)d);
return devices.ToList();
}
I don't believe you can use regular expressions with LINQ to Entities. However, it looks like you're just trying to find devices which start with "DEVICE", so the query would be:
return ctx.Devices.Where(d => d.DeviceId.StartsWith("DEVICE"))
.ToList();
EDIT: If you actually need the flexibility of a regular expression, you should probably first fetch the device IDs (and only the device IDs) back to the client, then perform the regular expression on those, and finally fetch the rest of the data which matches those queries:
Regex regex = new Regex(...);
var deviceIds = ctx.Devices.Select(d => DeviceId).AsEnumerable();
var matchingIds = deviceIds.Where(id => regex.IsMatch(id))
.ToList();
var devices = ctx.Devices.Where(d => matchingIds.Contains(d.DeviceId));
That's assuming it would actually be expensive to fetch all the data for all devices to start with. If that's not too bad, it would be a simpler option. To force processing to be performed in process, use AsEnumerable():
var devices = ctx.Devices.AsEnumerable()
.Where(d => regex.IsMatch(d.DeviceId))
.ToList();
You should always remember that your LinqToEntities queries must be translated to SQL queries. Since SQL Server has no support for regular expressions, this can not work.
As suggested in the comment by Paul Ruane, StartsWith will work. This can be translated by LinqToEntities into WHERE DeviceId LIKE 'DEVICE%'.
If StartsWith isn't enough because you may need to look for strings in the middle of database columns, Contains will also work:
var devices = from d in ctx.Devices
where d.DeviceId.Contains("DEVICE")
select d;
This will result in the following: WHERE DeviceId LIKE '%DEVICE%'.
Remember when using Entity Framework or Linq to Sql that your query ends up being translated to SQL. SQL doesn't understand your regular expression object, and can't use its matches on the server side. To use your RegEx easily you could instead retrieve all the devices from the server first, and then use your existing logic. e.g.
using (var ctx = new MyEntities())
{
var devices = from Device d in ctx.Devices select d;
// Retrieve all the devices:
devices = devices.ToList();
devices = from d in devices
let matches = searchTerm.Matches(d.DeviceId)
where matches.Count > 0
select ((Device)d);
return devices.ToList();
}
This does carry the cost of retrieving more data than you need, potentially much more. For complex logic you may want to consider a Stored Procedure, which could potentially use the same RegEx via CLR functions.
LinqToEntities does not support pushing Regex's down to the database. Just do Contains (which gets converted to sql... where DeviceId Like '%DEVICE%').
filterText = #"DEVICE.";
using (var ctx = new MyEntities())
{
var devices = from d in ctx.Devices
d.DeviceId.Contains(filterText)
select d;
return devices.ToList();
}