Let's say I have two tables:
Report
Comment
And assuming I have a database context:
var reports = db.Reports();
How can I make sure all Comments for each report are loaded as well?
At this point I want to disconnect from the database but still
have access to the comments. (For example:)
reports[0].Comments[0].Subject
I'm assuming that there is an 1-M FK relationship between reports and comments (1 Report can have many Comments)?
One option is to use the DataLoadOptions.LoadWith method - something like the following:
var reports = db.Reports();
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Reports>(r => r.Comments); // Ask for Comments along with reports
reports.LoadOptions = dlo;
Now, every time you select a report on that data context, the comments will be fetched from the db along with it.
Just beware that ALL fields from comments will be selected - there is no way using this method to select a subset of fields.
Another option is to be specific about what you want to select in the Linq query, e.g.
var myReportsList = from report in db.Reports
select new { // Using anonymous type, but could use a custom class
Report = report,
Comment = report.Comment.Detail, // for example
Subject = report.Comment.Subject
};
To understand when the query gets run and the database connection closed, you will need to understand:
The deferred execution model of Linq and Linq To Sql (Basically, for Linq to SQL, the query only runs when the results are asked for e.g. by iterating over the collection or binding to a grid)
The difference between IQueryable and IEnumerable
Jon Skeets "C# in depth" gives a great overview of these, and i've also heard very good things about "Linq in Action" - plus there are plenty of blog posts about these concepts which do the subjects more justice than I can do here ;o)
Keep in mind that if you use LoadOptions to define a multi-hop path (Reports, comments, anotherentity), the 3rd and further hops are loaded (if related over 1:n relationships) by code which is very inefficient: they'll execute one query per parent. For reports-comments, it's ok, they'll be fetched in 2 queries.
Related
I have an issue with next scheme, I attached it.I want to query from my database with only one object with "Manufacturer" class. Like:
var res = new XPQuery<Manufacturer>(session);
And then query all info that are related to my condition in LINQ.
I have tried XPLiteObject, XPObject, Association attribute, NoForeignKey Attribute, XPOCollection and a lot of stuff but nothing didn't help me.
I have tried a lot of approaches and every time I have new exception like:
SelectMany - method is not supported.
Can't set foreign key in table.
Duplicate primary key.
My question is: how to describe classes for normal extraction data from db?
UPD:
My solution now is: to use .ToList() at every object
and then use linq-query for join data and make needed query.
var manufacturer = new XPQuery<Manufacturer>(session).ToList();
var cars = new XPQuery<Car>(session).ToList();
var countries = new XPQuery<Country>(session).ToList();
var result = from m in manufacturer ....
So, I have found a solution to my question.
I downloaded DevExpress that can add templates for visual studio.
Then I select Add new item to my project named "DevExpress ORM DataModel Wizard".
This wizard can create persistent objects for existing database.
After that I can query database with next syntax:
var manufacturer = new XPQuery<Manufacturer>(session).Select(x => x....)...;
But if you want to use .SelectMany() in your LINQ query you should use .ToList() and then use .SelectMany(). I faced with a lot of issues when I have tried to join or perform some other LINQ related operations. Well, if you got some errors, firstly after .Select() try .ToList() and then perform your operation.
Suppose I have a collection (of arbitrary size) of IQueryable<MyEntity> (all for the same MyEntity type). Each individual query has successfully been dynamically built to encapsulate various pieces of business logic into a form that can be evaluated in a single database trip. Is there any way I can now have all these IQueryables executed in a single round-trip to the database?
For example (simplified; my actual queries are more complex!), if I had
ObjectContext context = ...;
var myQueries = new[] {
context.Widgets.Where(w => w.Price > 500),
context.Widgets.Where(w => w.Colour == 5),
context.Widgets.Where(w => w.Supplier.Name.StartsWith("Foo"))
};
I would like to have EF perform the translation of each query (which it can do indivudually), then in one database visit, execute
SELECT * FROM Widget WHERE Price > 500
SELECT * FROM Widget WHERE Colour = 5
SELECT W.* FROM Widget
INNER JOIN SUpplier ON Widget.SupplierId = Supplier.Id
WHERE Supplier.Name LIKE 'Foo%'
then convert each result set into an IEnumerable<Widget>, updating the ObjectContext in the usual way.
I've seen various posts about dealing with multiple result sets from a stored procedure, but this is slightly different (not least because I don't know at compile time how many results sets there are going to be). Is there an easy way, or do I have to use something along the lines of Does the Entity Framework support the ability to have a single stored procedure that returns multiple result sets??
No. EF deosn't have query batching (future queries). One queryable is one database roundtrip. As a workaround you can try to play with it and for example use:
string sql = ((ObjectQuery<Widget>)context.Widgets.Where(...)).ToTraceString();
to get SQL of the query and build your own custom command from all SQLs to be executed. After that you can use similar approach as with stored procedures to translate results.
Unless you really need to have each query executed separately you can also union them to single query:
context.Widgets.Where(...).Union(context.Widgets.Where(...));
This will result in UNION. If you need just UNION ALL you can use Concat method instead.
It might be late answer, hopefully it would help some one else with the same issue.
There is Entity Framework Extended Library on NuGet which provides the future queries feature (among others). I played a bit with it and it looks promising.
You can find more information here.
My database structure is this: an OptiUser belongs to multiple UserGroups through the IdentityMap table, which is a matching table (many to many) with some additional properties attached to it. Each UserGroup has multiple OptiDashboards.
I have a GUID string which identifies a particular user (wlid in this code). I want to get an IEnumerable of all of the OptiDashboards for the user identified by wlid.
Which of these two Linq-to-Entities queries is the most efficient? Do they run the same way on the back-end?
Also, can I shorten option 2's Include statements to just .Include("IdentityMaps.UserGroup.OptiDashboards")?
using (OptiEntities db = new OptiEntities())
{
// option 1
IEnumerable<OptiDashboard> dashboards = db.OptiDashboards
.Where(d => d.UserGroups
.Any(u => u.IdentityMaps
.Any(i => i.OptiUser.WinLiveIDToken == wlid)));
// option 2
OptiUser user = db.OptiUsers
.Include("IdentityMaps")
.Include("IdentityMaps.UserGroup")
.Include("IdentityMaps.UserGroup.OptiDashboards")
.Where(r => r.WinLiveIDToken == wlid).FirstOrDefault();
// then I would get the dashboards through user.IdentityMaps.UserGroup.OptiDashboards
// (through foreach loops...)
}
You may be misunderstanding what the Include function actually does. Option 1 is purely a query syntax which has no effect on what is returned by the entity framework. Option 2, with the Include function instructs the entity framework to Eagerly Fetch the related rows from the database when returns the results of the query.
So option 1 will result in some joins, but the "select" part of the query will be restricted to the OptiDashboards table.
Option 2 will result in joins as well, but in this case it will be returning the results from all the included tables, which obviously is going to introduce more of a performance hit. But at the same time, the results will include all the related entities you need, avoiding the [possible] need for more round-trips to the database.
I think the Include will render as joins an you will the able to access the data from those tables in you user object (Eager Loading the properties).
The Any query will render as exists and not load the user object with info from the other tables.
For best performance if you don't need the additional info use the Any query
As has already been pointed out, the first option would almost certainly perform better, simply because it would be retrieving less information. Besides that, I wanted to point out that you could also write the query this way:
var dashboards =
from u in db.OptiUsers where u.WinLiveIDToken == wlid
from im in u.IdentityMaps
from d in im.UserGroup.OptiDashboards
select d;
I would expect the above to perform similarly to the first option, but you may (or may not) prefer the above form.
I am very new to LINQ to SQL, so please forgive me if its a layman sort of question.
I see at many places that we use "select new" keyword in a query.
For e.g.
var orders = from o in db.Orders select new {
o.OrderID,
o.CustomerID,
o.EmployeeID,
o.ShippedDate
}
Why don't we just remove select new and just use "select o"
var orders = from o in db.Orders select o;
What I can differentiate is performance difference in terms of speed, i.e. then second query will take more time in execution than the first one.
Are there any other "differences" or "better to use" concepts between them ?
With the new keyword they are building an anonymous object with only those four fields. Perhaps Orders has 1000 fields, and they only need 4 fields.
If you are doing it in LINQ-to-SQL or Entity Framework (or other similar ORMs) the SELECT it'll build and send to the SQL Server will only load those 4 fields (note that NHibernate doesn't exactly support projections at the db level. When you load an entity you have to load it completely). Less data transmitted on the network AND there is a small chance that this data is contained in an index (loading data from an index is normally faster than loading from the table, because the table could have 1000 fields while the index could contain EXACTLY those 4 fields).
The operation of selecting only some columns in SQL terminology is called PROJECTION.
A concrete case: let's say you build a file system on top of SQL. The fields are:
filename VARCHAR(100)
data BLOB
Now you want to read the list of the files. A simple SELECT filename FROM files in SQL. It would be useless to load the data for each file while you only need the filename. And remember that the data part could "weight" megabytes, while the filename part is up to 100 characters.
After reading how much "fun" is using new with anonymous objects, remember to read what #pleun has written, and remember: ORMs are like icebergs: 7/8 of their working is hidden below the surface and ready to bite you back.
The answer given is fine, however I would like to add another aspect.
Because, using the select new { }, you disconnect from the datacontext and that makes you loose the change tracking mechanism of Linq-to-Sql.
So for only displaying data, it is fine and will lead to performance increase.
BUT if you want to do updates, it is a no go.
In the select new, we're creating a new anonymous type with only the properties you need. They'll all get the property names and values from the matching Orders. This is helpful when you don't want to pull back all the properties from the source. Some may be large (think varchar(max), binary, or xml datatypes), and we might want to exclude those from our query.
If you were to select o, then you'd be selecting an Order with all its properties and behaviours.
I'm sure this is straight forward but I'm very new to entity queries and has probably been asked before.
What i need to to search for all business in my database where they have a category that exists in a collection of categories I have built up
IList<businessCategory> busCatList;
busCatList.Add(businessCategory.CreatebusinessCategory(1,"Tourism"));
busCatList.Add(businessCategory.CreatebusinessCategory(2,"Accomidation"));
busCatList.Add(businessCategory.CreatebusinessCategory(3,"Entertainment"));
busCatList.Add(businessCategory.CreatebusinessCategory(4,"Bar"));
busCatList.Add(businessCategory.CreatebusinessCategory(5,"Club"));
var items = Data.DBEntities.business.Where(b.businessCategory.Contains(busCatList) );
I know the syntax of the query is wrong but essentially what i what the query to do it pull out all the business where it has a category matching any of the categories in the busCatLsit
In my database one business can be linked to many categories
In SQL I would do
SELECT name FROM business
join businessCategoryRlnshp on businessCategoryRlnshp.businessID = business.ID
where categoryID in (1,2,3)
just trying to read your mind here ;)
var items = busCatList.Where(businessCategory => b.businessCategory.Contains(businessCategory));
I can't really imagine a nice solution in linq - I mean other than some kind of performing the query several times - one for each business category.
However in SQL Server 2008 there is a new feature - passing a table variable to stored procedure. This can be done from code by passing a DataSet with 1 DataTable as a parameter.
You can of course write an extension method for IEnumerable to convert it to a DataSet similar to ToList() or ToDictionary() methods.
Stored procedure returning entities can be used in EntityFramework 1.0 so this should theoretically make the puzzle click.
PS> There's also a solution using E-SQL and probably query builder methods.