I am new to Entity Framework. I am bit confused with the difference in EF query and LINQ query. I have two tables and related queries listed below. Can you please tell me whether all these queries are LINQ or any of them are in EF? I need to write EF queries for selecting entire row, few columns and also joins. Your help or any relevant links would be highly appreciated.
Product_Details table
Product_ID, Product_Name, Price, Item_Desc, Stock_Avaialble, Created_Date
Sales_Details Table
Sales_ID, Product_ID, Qunatity, Total_Amont
var result = context.ProductDetails
where ProductID == 10
select new {ProductID, ProductName, Price}
var result = from prod in context.ProductDetails
where ProductID == 10
select new {ProductID, ProductName, Price}
var result = context.ProductDetails
.Where(p=>p.ProductID == 10)
.Select(p=> new Prod(p.ProductID, p.ProductName, p.Price))
var result1 = from prod in context.ProductDetails
join sales in context.SalesDetails on prod.ProductID == sales.ProductID
select new {prod.ProductID, prod.ProductName, sales.Qunatity, sales.TotalAmount}
Thanks
Peter
There is no such thing as an E.F. query. The queries you use when working with E.F. are LINQ. LINQ however does a whole lot more.
From E.F. documentation:
Entity Framework is an object-relational mapper (O/RM) that enables .NET developers to work with a database using .NET objects. It eliminates the need for most of the data-access code that developers usually need to write.
Entity Framework is a library used in C#.
From this article about LINQ on MSDN:
We use the term language-integrated query (LINQ) to indicate that query is an integrated feature of the developer's primary programming languages.
LINQ is part of C#.
General-purpose query facilities added to the .NET Framework apply to all sources of information, not just relational or XML data. This facility is called .NET Language-Integrated Query (LINQ).
The key here is the phrase "apply to all sources of information". All E.F. does is abstract away databases, and allow you to work with them as if they were normal enumerables in your program.
The standard query operators allow queries to be applied to any IEnumerable-based information source.
You use LINQ queries and extension methods for enumerables that LINQ provides to work with the "enumerables" (DB abstractions) that E.F. provides you with.
LINQ is a way of querying within you language of choice (VB, C#, .NET). It isn't directly related to EF. EF is something that maps to your database and you use LINQ as a way to query the database. It's just syntax that you use paired with EF to get data. You can also use LINQ on things such as collections.
As far as I understand your question, all your code returns queries associated with linq. They define operations to be done in the database but have not taken the trip to the db yet because they don't define execute commands(find, singleordefault, first, tolist etc). Linq is used for building and executing queries, like an addition to the EF language that also can do that but has limited usage. For databases linq builds queries and access the db via EF(or another ORM).
Some syntax like AsNoTracking(),Include(), ThenInclude() etc are EF syntax exclusively (meaning you have to refrence that library). Using linq syntax means you have to refrence linq(although most templates include it by default).
Related
I have an app using Entity Framework. I want to add a tree view listing products, grouped by their categories. I have an old SQL query that will grab all of the products and categories and arrange them into parent nodes and children. I am trying to translate it into LINQ that uses the EF. But the SQL has a WITH sub-query that I am not familiar with using. I have tried using Linqer and LinqPad to sort it out, but they choke on the WITH clause and I am not sure how to fix it. Is this sort of thing possible in LINQ?
Here is the query:
declare #id int
set #id=0
WITH ChildIDs(id,parentid,type,ChildLevel) AS
(
SELECT id,parentid,type,0 AS ChildLevel
FROM dbo.brooks_product
WHERE id = #id
UNION ALL
SELECT e.id,e.parentid,e.type,ChildLevel + 1
FROM dbo.brooks_product AS e
INNER JOIN ChildIDs AS d
ON e.parentid = d.id
WHERE showitem='yes' AND tribflag=1
)
SELECT ID,parentid,type,ChildLevel
FROM ChildIDs
WHERE type in('product','productchild','productgroup','menu')
ORDER BY ChildLevel, type
OPTION (MAXRECURSION 10);
When I run the query, I get data that looks like this (a few thousand rows, truncated here):
ID.....parentid.....type.....ChildLevel
35429..0............menu.....1
49205..0............menu.....1
49206..49205........menu.....2
169999.49206........product..3
160531.169999.......productchild..4
and so on.
The WITH block is a Common Table Expression, and in this case is used to create a recursive query.
This will be VERY difficult in Linq as Linq doesn't play well with recursion. If you need all of the data on one result set that a Stored Procedure would be easier. Another option is to do the recursion in C# (not in Linq but a recursive function) and do multiple round-trips. The performance will not be as good but if you result set is small it may not make much difference (and you will get a better object model).
You may be able to solve this using LINQ to Entities, but it is non-trivial and I suspect it will be very time consuming.
In situations like this, you may prefer to build a SQL View or Table-Valued Function that returns the results for which you're looking. Then import that View or Table-Valued Function into your EF model and you can pull data directly from it using LINQ.
Querying the View in LINQ is no different than querying a table.
To get data from a Table-Valued Function in LINQ, you pass the function's parameters in after the name of the function, like so:
var query = from tvf in _db.MyTableValuedFunction(parameters)
select tvf;
EDIT
As suggested by #thepirat000, Table-Valued Function support is not available in Entity Framework versions prior to version 5. In order to use this functionality, EF must be running with .NET 4.5 or higher.
At the end of the day, I could not get this to work. I ended up writing out a SQL query dynamically and sending that straight to the database. It works fine, and I am not relying on any direct user input so there is no chance of SQL injection. But it seems so old school! For the rest of my program I am using EF and LINQ.
Thanks for the replies!
My current database solution includes three tables called Establishment, Feature, and a linking many-to-many table called EstablishmentFeature (since an establishment can have many features, and a feature can exists across multiple establishments).
I need to generate a query that returns establishments that meet only certain criteria, namely, which establishments have X features based on a collection of featureId's being passed in. The establishment must have ALL features that are being search, i.e.. AND not OR condition.
I got the SQL to achieve the desired result, but I am pulling my hair out trying to work out the LINQ (lambra prefereably) equivalent. The T-SQL is:
SELECT e.[EstablishmentId], e.[Name], e.[Description]
FROM Establishment e
INNER JOIN EstablishmentFeature ef
ON e.[EstablishmentId] = ef.[EstablishmentId]
WHERE ef.[FeatureId] in ('20', '15', '72')
GROUP BY e.[EstablishmentId], e.[Name], e.[Description]
HAVING COUNT(*) = 3
I tried to use Linqer to convert the SQL but Linqer crashes when it attempts the conversion. I tried reinstalling Linqer, but it crashes without fail when trying to compile the LINQ syntax. (Simpler conversions work though). Also tried to work out the LINQ equivalent using LinqPad, but I just ended up chasing my tail...
Is this something I will have to use PredicateBuilder for? Somewhat exhausted, I don't want to go through the PredicateBuilder learning curve if there is a simple solution that is escaping me.
I'd try this (For all given ids there is any (= at least one) feature that has this given id):
var establishments = context.Establishments
.Where(e => featureIds.All(fid => e.Features.Any(f => f.FeatureId == fid)))
.ToList();
(featureIds is an IEnumerable<int> with the Ids being searched for.)
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.
I'm fairly new to nHibernate having come from an EF background and I'm struggling with the following query :
_patientSearchResultModel = (from patient in _patientRepository.Query(patientSearch.BuildPatientSpecification())
join admission in _admissionRepository.Query(patientSearch.BuildAdmissionSpecification())
on patient.Id equals admission.Patient.Id
orderby admission.AdmissionDate
select new PatientSearchResultModel(patient.Id,
admission.Id,
false,
_phaseTypeMapper.GetPhaseTypeModel(admission.PhaseType),
patient.Last, patient.First,
admission.InPatientLocation,
admission.AdmissionDate,
admission.DischargeDate,
admission.RRI,
null,
admission.CompletionStatus,
admission.FollowupStatus)).ToList();
The intent of this query is to allow users to filter the two queries on parameters built up using the two Build???Specification functions and return the resultset. There could be many admission records and I would only like one PatientSearchResultModel per patient object, with the admission object being the newest one by Admission Date.
These objects are coming from nHibernate and it keeps return a Not Supported exception. There is also an association between Patient and Admissions thus : Patient.Admissions but i couldn't figure out how to then add the query filters return from the function Build???Specifications.
I'd be really grateful if someone could point me in the right direction; am I up against the Linq provider implementation here in nHibernate and need to move to Criteria or is it my Linq query ?
If anyone has any links or suggestions for good books or other learning materials in this area that would also be really helpful too.
I see several potential problems:
If you're using NHibernate 2.x + Linq2NHibernate explicit joins like that are not supported; in other versions they're just considered a smell.
I dont think NHibernate supports calling parameterized constructors in select clauses
I'm very sure NHibernate does not support calling instance methods in the select lambda
I'd suggest using the lambda syntax and SelectMany to alleviate potential join issues. Points #2 & #3 can be solved by projecting into an anonymous type, calling AsEnumerable then projecting into your model type.
Overall I'd suggest restructuring your code like:
var patientSpec = patientSearch.BuildPatientSpecification();
var admissionSpec = patientSearch.BuildAdmissionSpecification();
_patientSearchResultModel = _patientRepository.Where(patientSpec)
.SelectMany(p=>p.Admissions).Where(admissionSpec)
.Select(a=> new {
PatientId = a.Patient.Id,
AdminssionId = a.Id,
a.PhaseType,
a.Patient.Last,
a.Patient.First,
a.InPatientLocation,
a.AdmissionDate,
a.DischargeDate,
a.RRI,
a.CompletionStatus,
a.FollowupStatus
}).AsEnumerable()
.Select(x=> new PatientSearchResultModel(x.PatientId, x.AdmissionId ...))
.ToList();
Divide your query into parts and check which part runs and which doesn't.
My take on this is that select new ... is not supported in Linq to nHibernate.
I would recomend using something else, because it is simply too imature and feature-less to use seriously.
As with most popular LINQ-to-Database query providers, NHibernate will try to translate the whole query into a SQL statement to run against the database. This requires that all elements of your query are possible to express in the SQL flavour you're using.
In your query, the select new statement cannot be expressed in SQL, because you're making a call to the constructor of your PatientSearchResultModel class and are making a call to a GetPhaseTypeModel method.
You should restructure your query to express what you want to execute on the SQL database, then call AsEnumerable() to force the remainder of the query to be evaluated in-memory. After that call, you can call the constructor of your class and any .NET methods, and they will be executed as native code.
This query is too complex to describe it using Linq. It would give wrong result finally (if Patient has more than one admission records, result would have duplicate entries).
I see two steps for solution:
1) At development stage, use in-memory query. So, take Patients using ToList() first (query db at this moment). Some predicates (Patient filter like MRN, First, Last) could be used at this stage.
And then do search in-memory. Not performance, but working solution. Mark it for refactor to optimize later.
2) Finally, use NHibernate IQuery (ISQLQuery) and build sql query manually to make sure it would work as expected and work fast enough on SQL Server side. This is just read-only query and do not require Nhibernate query engine (Linq to Nhibernate) at all.
Which ORM supports sql like batch insert/update/delete:
var user=new UserInfoFields();
var update=user.Update().Set
(
user.Field1=1,
user.Field2="xxxx"
).Where(user.Name=="Jim" && user.Enable==true);
update.Excute();
The corresponding T-sql is:
UPDATE UserInfo
SET
Field1=1,
Field2="xxxx"
WHERE Name='Jim' and Enable=1
Checkout BLToolkit -> BLToolkit Linq Extensions - Update
db.Employee
.Where(e => e.Title == "Spectre")
.Update(e => new Northwind.Employee
{
Title = "Commander"
});
or
db.Employee
.Where(e => e.Title == "Spectre")
.Set(e => e.Title, "Commander")
.Update();
=
UPDATE
[e]
SET
[Title] = 'Commander'
FROM
[Employees] [e]
WHERE
[e].[Title] = 'Spectre'
Been using it for 2-3 years now and its great :D
First read this though ->
High Level Vision, Global Architecture Strategy & Concept Model Design
PHP ActiveRecord has something like this, but that's PHP. Linq2SQL can be extended to perform simpler batch updates/deletes, but it's not "stock" behavior. Here's the link to an article on the topic: http://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx. I know for a fact that NHibernate has nothing like this built in, but again, you can extend the Linq provider, and NH also allows HQL and SQL queries as strings, including batch updates/deletes (only problem is they're "magic strings" that are not compiler-checked).
This kind of behavior really goes against what an ORM is designed to do. ORMs exist not to provide compiler-checked queries for all possible SQL operations, but to provide "black-box" encapsulated logic for CRUD operations of single instances of objects, for instance, turning a request for an object into SQL that retrieves the necessary data and hydrates the object. Batch and bulk operations are not their forte by any means.
Most of ORMs I know lacks the bulk updates functionality, if you prefer working with EnityFramework like me you can use the Entity Framework Extended Library wich extends many functionalities upon EntityFramework including bulk updates and deletes and Future queries.