I have summarized my problem in following code.
NorthwindDataContext dc = new NorthwindDataContext();
var query = from c in dc.Customers
select c;
Above code is generating following sql statement
SELECT [t0].[ID], [t0].[FirstName], [t0].[LastName]
FROM [dbo].[Customer] AS [t0]
Now i want to modify the above generated query something like this
SELECT [t0].[ID], [t0].[FirstName], [t0].[LastName] FROM [dbo].[Customer]
AS [t0] WITH (nolock)
Is it possible in linq to modify the generated query?If yes then how?
You will not be able to modify the generated L2S T-SQL code directly, the way you want (unless you modify the transaction isolation level). However, we've dealt with situations like this, fairly simply, by creating a view with lock hints we want in place and querying the view, instead of the table directly.
I have found a very handy tips for modifying the linq generated sql statement.
NorthwindDataContext db = new NorthwindDataContext();
if (db.Connection.State == System.Data.ConnectionState.Closed)
db.Connection.Open();
var cmd = db.GetCommand(db.Customers.Where(p => p.ID == 1));
cmd.CommandText = cmd.CommandText.Replace("[Customers] AS [t0]", "[Customers] AS [t0] WITH (NOLOCK)");
var results = db.Translate(cmd.ExecuteReader());
Maybe these pages will help you..
http://www.infoq.com/news/2008/03/linq-nolock
http://coolthingoftheday.blogspot.com/2008/03/linq-to-sql-nolock.html
which refers hanselmans blog entry
http://www.hanselman.com/blog/GettingLINQToSQLAndLINQToEntitiesToUseNOLOCK.aspx
or check out this question
NOLOCK with Linq to SQL
Related
T-SQL Query
Select * from dbo.User_Users
Where UserID IN (Select UserID from Course_Enrollments)
LINQ to Entities alternative of Above Query
var innerquery = from en in Course_Enrollments
select en.UserID;
var query = from u in User_Users
where innerquery.Contains(u.UserID)
select u;
There are alot of complex subqueries on stackoverflow, i just want to see a simple example of how a simple subquery is done via linq.This is how i done it, however its not good because it sends 2 queries to the database.
Simple answer is use the "let" keyword and generate a sub-query that supports your conditional set for the main entity.
var usersEnrolledInCourses = from u in User_Users
let ces = from ce in Course_Enrollments
select ce.UserID
where ces.Contains(u.UserID)
select u;
This will create an exists block in TSQL similar to
SELECT [Extent1].*
FROM dbo.User_Users AS Extent1
WHERE EXISTS (SELECT 1 AS [C1]
FROM dbo.Course_Enrollements AS Extent2
WHERE (Extent2.UserID = Extent1.UserId))
It's close to what you've asked for and will generally create the same query plan on SQL Server.
Hope this helps!
from u in User_Users
where u.Course_Enrollments.Any()
select u
if you have the foreign keys set up. If not you can do this
from u in User_Users
join cu in Course_Enrollments on u.UserId equals cu.UserId
select u
You also should wrap any of these with .Distinct() call
My sql code is below, I'm trying to Convert it to linq. I'm getting stuck on how to do row_number() over (partition part. If i can get some guidance or assistance please and thank you.
with summary AS
(select * from
(select p.loan_guid,
p.TransactionDate,
p.balanceoutstanding,
row_number() over (partition by p.loan_guid
order By linenumber desc) as rk
from (select * from transactions1
where transactiondate <= #EndDate )as p )
as S where S.rk = 1)
I am having trouble finding a definitive answer, but my guess would be that Linq does not support analytic/window functions. If you are using Entity Framework, then you can always designate a type, execute the raw query and EF will map and track the results for you. Here is an example:
using(var ctx = new MyContext){
var myObjects = ctx.Products.SqlQuery("<Your Query>").ToList();
}
the result will be a list of objects of type Product.
This creates a dependency in your application on a SQL database, but I would prefer to have a clean SQL query that I can refactor later if necessary, Then an enormous Linq query in your code.
I have encountered something that puzzles me and I would like to see your opinion on the matter. It turns out that linq to sql and entity framework threats consecutive order by's differently.
The following code is used just for example and I am not claiming it has any sense at all:
Linq to sql:
DataClasses1DataContext db = new DataClasses1DataContext();
var result = (from c in db.Products
orderby c.ProductName
orderby c.UnitPrice
orderby c.UnitsOnOrder
select c).ToList();
What it generats on the server side:
SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
ORDER BY [t0].[UnitsOnOrder], [t0].[UnitPrice], [t0].[ProductName]
The same test with Entity Framework generates this:
SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[SupplierID] AS [SupplierID],
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[QuantityPerUnit] AS [QuantityPerUnit],
[Extent1].[UnitPrice] AS [UnitPrice],
[Extent1].[UnitsInStock] AS [UnitsInStock],
[Extent1].[UnitsOnOrder] AS [UnitsOnOrder],
[Extent1].[ReorderLevel] AS [ReorderLevel],
[Extent1].[Discontinued] AS [Discontinued]
FROM [dbo].[Products] AS [Extent1]
ORDER BY [Extent1].[UnitsOnOrder] ASC
As you can see Linq To Sql adds all the requested order by's where the last one has the highest priority (which in my opinion is correct).
On the other hand entity framework respects only the last order by and disregards all the others.
Now I know there is an order by then by clause that can be used but I am just wondering which behavior is more correct. Also as far as I remember the query extenders used in asp are working with a separate order by which if applied on a query generated from a different data source will not work correctly (according to the above example one of the order by's will be omitted)
My opinion is that EF is correct. I don't know why L2S would do what you're describing - in my opinion, if you add an OrderBy clause instead of using ThenBy, it should overwrite any existing OrderBys.
When you're working with Linq-To-Objects, you should see OrderBy replace any previous ones, so it makes more sense to me to have the data-driven LINQ act the same.
If the behavior changed the way you're describing, then it seems that Microsoft agrees, since EF was designed to replace L2S.
What i've learned is that the order by is written like this:
DataClasses1DataContext db = new DataClasses1DataContext();
var result = (from c in db.Products
orderby c.UnitsOnOrder, c.UnitPrice, c.ProductName
select c).ToList();
And like that you can see the order clear to every one.
I created an Entity Framework model that contains two tables from the Northwind database to test some of its functionality: Products and CAtegories.
It automatically created an association between Category and Product which is 0..1 to *.
I wrote this simple query:
var beverages = from p in db.Products.Include("Category")
where p.Category.CategoryName == "Beverages"
select p;
var beverageList = beverages.ToList();
I ran SQL Profiler and ran the code so i could see the SQL that it generates and this is what it generated:
SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[SupplierID] AS [SupplierID],
[Extent1].[QuantityPerUnit] AS [QuantityPerUnit],
[Extent1].[UnitPrice] AS [UnitPrice],
[Extent1].[UnitsInStock] AS [UnitsInStock],
[Extent1].[UnitsOnOrder] AS [UnitsOnOrder],
[Extent1].[ReorderLevel] AS [ReorderLevel],
[Extent1].[Discontinued] AS [Discontinued],
[Extent3].[CategoryID] AS [CategoryID],
[Extent3].[CategoryName] AS [CategoryName],
[Extent3].[Description] AS [Description],
[Extent3].[Picture] AS [Picture]
FROM [dbo].[Products] AS [Extent1]
INNER JOIN [dbo].[Categories] AS [Extent2]
ON [Extent1].[CategoryID] = [Extent2].CategoryID]
LEFT OUTER JOIN [dbo].[Categories] AS [Extent3]
ON [Extent1].[CategoryID] = [Extent3].[CategoryID]
WHERE N'Beverages' = [Extent2].[CategoryName]
I am curious why the query inner joins to Categories and then left joins to it. The select statement is using the fields from the left joined table. Can someone help me understand the reason for this? If I remove the left join and change the select list to pull from Extent2 I get the same results for this query. In what situation would this not be true?
[Extent3] is a realization of Include(Category) and Include should not impact on result of selection from "main" table Product, so LEFT JOIN (all records from Product and some records from the right table Category).
[Extent2] is really to filter all records by related table Category with name "Beverages", so in this case it is the strong restriction (INNER JOIN)
Why two? :) Because of parsing expression-by-expression and auto generation for every statement (Include, Where)
You'll notice that the query is pulling all columns in the SELECT list from the copy of the Categories table aliased Extent3, but it's checking the CategoryName against the copy aliased Extent2.
In other words, in this scenario EF's query generation is not realizing that you're Include()ing and restricting the query via the same table, so it's blindly using two copies.
Unfortunately, beyond explaining what's going on, my experience with EF is not advanced enough to suggest a solution...
djacobson and igor explain pretty well why this happens. The way I personally use the Entity Framework, I avoid using Include altogether. Depending on what you're planning to do with the data, you could do something like this:
var beverages = from p in db.Products
select new {p, p.Category} into pc
where pc.Category.CategoryName == "Beverages"
select pc;
return beverages.ToList().Select(pc => pc.p);
... which, at least in EF 4.0, will produce just a single inner join. Entity Framework is smart enough to make it so that the product's Category property is populated with the category that came back from the database with it.
Of course, it's very likely that SQL Server optimizes things away so this won't actually gain you anything.
(Not directly an answer to your question if the queries are the same, but the comment field is too restricting for this)
If you leave out the .Include(), doesn't it load it anyway (because of the where)? Generally it makes more sense to me to use projections instead of Include():
var beverages = from p in db.Products.Include("Category")
where p.Category.CategoryName == "Beverages"
select new { Product = p, Category = p.Category };
var beverageList = beverages.ToList();
I have an application in which I am using a stored procedure and LINQ.
My procedure looks like this:
myProc
select col1, Col2, Col3 from Tab1 inner join Tab2 on col1=ColA join tab3 on Col1=ColD
Select cola, Colb, Colc from Taba inner join Tabb on cola=ColX join tabc on Cola=ColY
Select colP, ColQ, ColR from TabP inner join TabQ on colP=ColW join tabR on ColP=ColZ
I am executing this stored procedure in LINQ.
When I execute it I am getting the results in IMultipleResults.
Below is my code in LINQ:
[Function(Name = "dbo.MyProc")]
[ResultType(typeof(TabA))]
[ResultType(typeof(TabB))] .....
public IMultipleResults GetMultipleResults([Parameter(DbType = "VarChar(50)")] string i_Cola)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), i_Cola);
return (IMultipleResults)result.ReturnValue;
}
When I execute it as follows:
MyContext mCtx = new MyContext()
var allResult = mCtx.GetMultipleResults(txtName.Text.Trim());
IEnumerable<Taba> TabaRes = allResult.GetResult<Taba>();
IEnumerable<TabB> TabbRes = allResult.GetResult<Tabb>();
I am getting the column values of tables but I want the Inner Joined columns also.
I've referred to many blogs and forums, such as...
Ben Hall's Blog
Guy Burstein's Blog
Microsoft's Blog
... to try to find a solution to my problem, but couldn't find any.
well better to use views in respect to SP(If u are not able to write a linq to sql query),if u are using Linq to Sql its worthLess to use Sp becoze it decrease the performance.and one more thing if u are using Linq to sql there is no Need to use any type of join if ur data base is completely normalized.
If still ur prob is not solved just show me the table structure and what the out u need i will write a query for u...
I am not sure I understand your need, but can you change the proc to return * or all the columns in all the tables you need?
If the stored procedure isn't returning the data required then the only option for LINQ would be for it to go query the database again itself.
This would mostly negate the point of having a stored procedure and be slower than just adding the required parameters to your stored procedure.
Maybe this would be a stupid question, but in your store procedure:
select col1, Col2, Col3 from Tab1
inner join Tab2 on col1=ColA join
tab3 on Col1=ColD
col1,col2,col3 are all from tab1, but you never did a select from the other tables that you are trying to do inner join. Did you tried
select col1,col2,col3,colA,colB...
-or-
select * from...