Create DateTime within LINQ query - c#

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()

Related

How to set date format "yyyy-MM-dd hh:mm" in linq?

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")
});

Entity Framework Exclude Fields Query Count and POCO best way

I created a qr object to get total item count without getting all data from database and also if necessary to select MyViewModel list
var qr = dbSet.Select(o =>
new { ParentID = o.Parent.ID, o.Parent.Name, o.ID})
.Select(o => new MyViewModel(o.ParentID, o.Name, o.ID));
But when I tried qr.Count() and qr.ToList() they all run same query in database which is for items not only for items' count.
What is the best and fastest way to get 'MyViewModel' items' itself or items' count or both at the same time?
The problem with this query is because it calls a constructor of MyViewModel in
.Select(o => new MyViewModel(o.ParentID, o.Name, o.ID))
This call effectively converts your IQueryable to IEnumerable, as it is not possible to call a constructor from a query.
To avoid this conversion, use object initializer instead of constructor:
.Select(o => new MyViewModel
{
ParentID = o.ParentID,
Name = o.Name,
ID = o.ID
})
You have .AsEnumerable() call in your linq query. That means that any translate-your-query-into-SQL stops right there, and anything after will not be translated to SQL. Therefore, the only query that will be run in your database is the retrieval of you complete dbSet. If you want to only retrieve the count, than run the following linq query
var qrCount = dbSet.Count();

How to convert this complex Entity Framework query into a standard SQL query? What exactly perform?

I have no experience with .NET Entity Framework and I have to understand what exactly do this Entitity Framework query and translate in in classic SQL (for Microsoft SQL server)
So I have this query:
using (MyCorp.EarlyWarnings.Model.EarlyWarningsEntities context = new Model.EarlyWarningsEntities())
{
DBContext.SetTimeout(context);
float vulnerabilities_thisweek = (from x in context.VulnerabilityAlertDocuments
.Select(p => new { p.Id, p.Published, p.Title, p.Severity, p.LastUpdated })
.AsEnumerable()
.Select(p => new MyCorp.EarlyWarnings.Model.VulnerabilityAlertDocument()
{
Id = p.Id,
Published = p.Published,
Title = p.Title,
Severity = p.Severity,
LastUpdated = p.LastUpdated
})
.Where(p => p.LastUpdated.Date > DateTime.Now.AddDays(-7).Date)
select x).Count();
}
I know that the result of this query on my database is -1,00 (I know this information executing this query)
I also know that this query work on a single table (or at least I think it is so, correct if I am saying wrong thing) because I have from x in context.VulnerabilityAlertDocuments and in the EarlyWarningsEntities class I found this property that map the Data Base table named as VulnerabilityAlertDocument on the DbSet object named VulnerabilityAlertDocuments:
public DbSet<VulnerabilityAlertDocument> VulnerabilityAlertDocuments { get; set; }
So I think that my SQL query have to work only on the VulnerabilityAlertDocument database table.
I can't understand what exactly do when in the where condition use the => "operator", I have try to search on Google but I can't find nothing
I also have some difficulties to understand what exactly do the AsEnumerable() method called on the .Select() result.
Reading the documentation it seems to me that the first .Select() method return to me a set of rows and then it is called the AsEnumerable() method to have an iterator on this collection but I am not sure, do you confirm or is it wrong?
Then it execute a second select and I can't understand on what (it seems to me that the table is the same)
Someone can help me to understand what exactly do this query and how can I convert it in standard SQL?
Tnx
Your query is creating an anonimous type just for nothing, i have not tested but i think something like the following will produce the same results:
float vulnerabilities_thisweek = (from x in context.VulnerabilityAlertDocuments
.Where(p => p.LastUpdated > DateTime.Now.AddDays(-7))
.Count();
}
also i recomend you to take a look to LinqPad, you can test your linq queries and see the corresponding sql statements
This seems to be overly complicated for a COUNT query..
From what I see, this can translate into:
SELECT COUNT(*) FROM VulnerabilityAlertDocuments WHERE DateDiff(day, LastUpdated, GetDate()) < 8

Creating a single Type from muliple entities in Lambda

I have 3 entities
I'd like to flatten the tblCondition and BusinessAreas into one object. What I want is Category.ID, Category.Category, BusinessArea.ID, BusinessArea AreaName.
I know this can be done by creating an Anonymous type with Lambda but I'm relatively unskilled with Lampda or LINQ.
Forgot to mention that I need to get to the two tables through the first one.
My original call looks like this.
myConditionTemplate = EE.ConditionTemplates.Where(c => c.TemplateCode == TextBoxSearchConditionCode.Text).FirstOrDefault();
Here's the official documentation: http://msdn.microsoft.com/en-us/library/vstudio/bb384105.aspx
Essentially in your select portion use the new keyword without a class name like:
select new { Category.ID, Category.Category, BusinessArea.ID, BusinessArea.AreaName }
The webpage only shows an example using Linq in query form, but to do it in method form:
var results = db.GetStuff().Select(x => new { x.ID, x.Name });
Ack, that may not be very clear. I just found some great examples at How to do a join in linq to sql with method syntax?. This was a different question, but the answer's example shows you how to do the lamba for a joined enumerable set.
UPDATE: Since you updated your question, see if this helps:
var results = myConditionTemplate.Select(x => new { CategoryID = x.tblCondition.ID, Category = x.tblCondition.Category, BusinessAreaID = x.tblCondition.BusinessArea.ID, AreaName = x.tblCondition.BusinessArea.AreaName});

Where statement with list of keys

My problem is that I cannot get Where statement working correctly with Entity Framework.
I have a class that has int and long properties that define one row in the database. Let's call those properties Id & Parent
public class Update
{
public long Id { get; set; }
public int Parent { get; set; }
}
Then I have list of those Updates and I want that each database row should match one those updates (both properties) in the list.
What I have tried is that I convert those updates to an anonymous type and try to find only those rows that have a perfect match: both int & long are same.
// anon type
var mapping = updates.Select(o => new { id = o.Id, parent = o.Parent}).ToList();
var results = from fa in Uvw_MyTable
// PROBLEMATIC WHERE
where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
select new { fa };
But unfortunately I always get an error: Unable to create a constant value of type 'Anonymous type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
I have also tried to use Any like this:
where mapping.Any(a => fa.Id == a.id && fa.Parent == a.parent)
But I get the same error. The same thing happens also when I use the List of Update objects. Unable to create a constant value of type 'xxx.Update'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
Any thoughts how to solve this issue?
Update
This exactly same query works very well in the LINQPad 4
Update 2
Is the problem related to this question?
Update 3
As Maarten pointed out this problem needs solution that uses different approach to re-produce the same results.
You are actually executing two queries in your code.
The first query is:
var mapping = updates.Select(o => new { id = o.Id, parent = o.Parent}).ToList();
The second query is (ok, the query is not iterated over, so technically the query is not yet executed here - nitpicking):
var results = from fa in Uvw_MyTable
where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
select new { fa };
The first query is defined and executed in your single statement since you are using the ToList() method. Since this is now a list of objects, instead of the IQueryable, EF cannot translate this into SQL. You have to leave it as an IQueryable. If you change it to the following, it should work.
var mapping = updates
.Select(o => new { id = o.Id, parent = o.Parent}); // NOT ToList() !!
var results = from fa in Uvw_MyTable
where mapping.Contains(new { id = fa.Id, parent = fa.Parent })
select new { fa };
To explain the error that EF gives - EF can only translate either IQueryable's into SQL, or primitive types (ints, strings, etc) into parameters. EF cannot translate objects into SQL, since it has no way of transporting the value of objects to the database in a meaningful way.
UPDATE:
The first query (I see now) is not a query at all, it's source is a variable called updates. If this is a list of objects in-memory, than this query cannot be translated as such, and you have to redesign you query (for example, loading Uvw_MyTable is memory). If 'updates' is an IQueryable (from the same context), than my answer given above should work.
I'm not sure I've understood your code/question correctly, but it would seem to me that something like this should work:
var results = from fa in Uvw_MyTable
where updates.Any(u => u.Id fa.Id && u.Parent = fa.Parent)
select fa;
I'm not clear on what your desired behaviour with the OtherTable is, but the general form of the linq expression above is a lot more efficient than the one you're using.
The key point is that you don't need to create anonymous types in order to compare multiple fields; therefore the first select (into mapping) is redundant.
In entity framework or Linq to sql, linq queries will ultimately be translated to sql queries. your linq query cant be translated to sql queries as you are using types or classes which is not convertible to sql .

Categories