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();
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()
i just don't understand the meaning of writing AsEnumerable() in linq query.
i am having one UserDetail table in which i am fetching all details of user and i want to take
name,email in to my model.
var data = context.UserDetails
.Select(temp => new FullName = temp.Fullname, Email = temp.Email })
.ToList()
.AsEnumerable()
.Select(d => new UserDetailsModel { Fullname = d.FullName, Email = d.Email })
.ToList();
What is the meaning of AsEnumerable() as because when i am removing this there is no error but as i have seen some queries where they are using this method.
And does anybody have better approach for taking anonymous object value in to my View Model?
Does it improve performance? What is the significance of this method? Can anybody explain me this method in context to my question and details?
Your first select is querying the database and returns IQueryable<T>. .AsEnumerable() make it IEnumerable<T>. IQueryable<T> extends IEnumerable<T> so whatever you can do with IEnumerable<T>, you can also do with IQueryable<T>.
Another big difference is that IEnumerable<T> fetches the entire table and applies the query on that afterwards, whereas IQueryable<T> only fetches the filtered data.
Note that AsEnumerable() does not materialise the query yet. You often use .ToList() to materialize your query so other non sql statements can be performed on the result set as per this example
You can simplify your code to
var data = (from temp in context.UserDetails select temp)
.Select(d => new UserDetailsModel
{
Fullname = d.fullName,
Email = d.Email
}).ToList());
ToList() or AsEnumerable() work similarly, you don't need both. List is a IEnumerable + some extra features such as Add(), Count, etc., and the idea of using any of these is to materialize the query (IQueryable).
Also, You don't need the temp query, you could do a direct select:
var data = context.UserDetails
.Select(d => new UserDetailsModel {...})
.ToList()); // or AsEnumerable()
I'm passing an OData query into a method, but I need perform an additional join to the query to retrieve some related data, as we want to get it all in one round trip to the DB.
var products = query.ApplyTo(_repository.Query, ODataQuerySettings)
.Cast<Product>()
.ToList();
// Ideally, this will be the only query that's run.
var productImages = products.GroupJoin(_imageRepository.Query, p => p.ProductId, image => image.ProductId, (product, image) => new {
Product = product,
Image = image.DefaultIfEmpty()
}).ToList();
foreach (var item in productImages) {
...
}
This works, but is doing it with two queries. It seems that ApplyTo executes the query against the DB, rather than just providing you with a mutable IQueryable. If I remove the ToList() call from the first query, it throws an exception.
Is there any way to do this?
I have a database where I'm wanting to return a list of Clients.
These clients have a list of FamilyNames.
I started with this
var query = DbContext.Clients.Include(c => c.FamilyNames).ToList() //returns all clients, including their FamilyNames...Great.
But I want somebody to be able to search for a FamilyName, ifany results are returned, then show the clients to the user.
so I did this...
var query = DbContext.Clients.Include(c => c.FamilyNames.Where(fn => fn.familyName == textEnteredByUser)).ToList();
I tried...
var query = DbContext.Clients.Include(c => c.FamilyNames.Any(fn => fn.familyName == textEnteredByUser)).ToList();
and...
var query = DbContext.FamilyNames.Include(c => c.Clients).where(fn => fn.familyname == textEnteredByUser.Select(c => c.Clients)).ToList();
What I would like to know (obviously!) is how I could get this to work, but I would like it if at all possible to be done in one query to the database. Even if somebody can point me in the correct direction.
Kind regards
In Linq to Entities you can navigate on properties and they will be transformed to join statements.
This will return a list of clients.
var query = DbContext.Clients.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser)).ToList();
If you want to include all their family names with eager loading, this should work:
var query = DbContext.Clients.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser)).Include(c => c.FamilyNames).ToList();
Here is some reference about loading related entities if something doesn't work as expected.
You can use 'Projection', basically you select just the fields you want from any level into a new object, possibly anonymous.
var query = DbContext.Clients
.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser))
// only calls that can be converted to SQL safely here
.Select(c => new {
ClientName = c.Name,
FamilyNames = c.FamilyNames
})
// force the query to be materialized so we can safely do other transforms
.ToList()
// convert the anon class to what we need
.Select(anon => new ClientViewModel() {
ClientName = anon.ClientName,
// convert IEnumerable<string> to List<string>
FamilyNames = anon.FamilyNames.ToList()
});
That creates an anonymous class with just those two properties, then forces the query to run, then performs a 2nd projection into a ViewModel class.
Usually I would be selecting into a ViewModel for passing to the UI, limiting it to just the bare minimum number of fields that the UI needs. Your needs may vary.
So I am trying to order a query by an int var that is in an ordered list of the same int vars; e.g. the query must be sorted by the lists order of items. Each datacontext is from a different database which is the reason i'm making the first query into an ordered list of id's based on pet name order, only the pet id is available from the second query's data fields, Query looks like:
using (ListDataContext syndb = new ListDataContext())
{
using (QueryDataContext ledb = new QueryDataContext())
{
// Set the order of pets by name and make a list of the pet id's
var stp = syndb.StoredPets.OrderBy(x => x.Name).Select(x => x.PetID).ToList();
// Reorder the SoldPets query using the ordered list of pet id's
var slp = ledb.SoldPets.OrderBy(x => stp.IndexOf(x.petId)).Select(x => x);
// do something with the query
}
}
The second query is giving me a "Method 'Int32 IndexOf(Int32)' has no supported translation to SQL." error, is there a way to do what I need?
LINQ to SQL (EF) has to translate your LINQ queries into SQL that can be executed against a SQL server. What the error is trying to say, is that the .NET method of IndexOf doesn't have a SQL equivalent. You may be best to get your data from your SoldPets table without doing the IndexOf part and then doing any remaining ordering away from LINQ to SQL (EF).
Something like this should work:
List<StoredPet> storedPets;
List<SoldPet> soldPets;
using (ListDataContext listDataContext = new ListDataContext())
{
using (QueryDataContext queryDataContext= new QueryDataContext())
{
storedPets =
listDataContext.StoredPets
.OrderBy(sp => sp.Name)
.Select(sp => sp.PetId)
.ToList();
soldPets =
queryDataContext.SoldPets
.ToList();
}
}
List<SoldPets> orderedSoldPets =
soldPets.OrderBy(sp => storedPets.IndexOf(sp.PetId))
Note: Your capitalisation of PetId changes in your example, so you may wish to look at that.
LinqToSql can't transalte your linq statement into SQL because there is no equivalent of IndexOf() method. You will have to execute the linq statement first with ToList() method and then do sorting in memory.
using (ListDataContext syndb = new ListDataContext())
using (QueryDataContext ledb = new QueryDataContext())
{
var stp = syndb.StoredPets.OrderBy(x => x.Name).Select(x => x.PetID).ToList();
// Reorder the SoldPets query using the ordered list of pet id's
var slp = ledb.SoldPets.ToList().OrderBy(x => stp.IndexOf(x.petId));
}
You can use this, if the list size is acceptable:
using (ListDataContext syndb = new ListDataContext())
{
using (QueryDataContext ledb = new QueryDataContext())
{
var stp = syndb.StoredPets.OrderBy(x => x.Name).Select(x => x.PetID).ToList();
var slp = ledb.SoldPets.ToList().OrderBy(x => stp.IndexOf(x.petId));
// do something with the query
}
}