LINQ to SQL Insert - linq

i'm using LINQ To SQL to perform an insert via db.table.InsertOnSubmit(). I'm wondering if there is a way to reproduce the T-SQL version of the 'where not exists (select etc etc) begin insert into etc etc end' as one single query? Thanks, Martin

LINQ has an extension method called Contains which allows for this functionality. This can be seen in the following example:
NorthwindDataContext dc = new NorthwindDataContext();
dc.Log = Console.Out;
var query =
from c in dc.Customers
where !(from o in dc.Orders
select o.CustomerID)
.Contains(c.CustomerID)
select c;
foreach (var c in query) Console.WriteLine( c );
Note the negation on the where clause!
This example was from the website here.

Nothing build in as far as I know, we would have to go about finding the row manually using where and than do the Insert.
There is a possibility of race coditions in such queries. Have a look at this thread for detailed solution :
http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/b1a0eb5b-d5d3-41af-829f-bbbac47b7383/

Related

optimize linq query with multiple include statements

The linq query takes around 20 seconds for executing on some of the data . When converted the linq to sql there are 3 nested joins that might be taking more time for execution . Can we optimize the below query .
var query = (from s in this.Items
where demoIds.Contains(s.Id)
select)
.Include("demo1")
.Include("demo2")
.Include("demo3")
.Include("demo4");
return query;
The expectation is to execute the query in 3-4 seconds which is now taking around 20 secs for 100 demoIds .
As far as your code is concerned it looks like it's the best way to get what you want (Assuming Includeing "demo3" twice is a typo for this example.).
However, the database you use will have a way to optimize your queries or rather the underlying data structure. Use whatever tool your database provider has to get an execution plan of the query and see where it spends so much time. You might be missing an index or two.
I advice lazy loading or join query.
Probably SQL output is this query;
(SELECT .. FROM table1 WHERE ID in (...)) AS T1
(INNER, FULL) JOIN (SELECT .. FROM table2) AS T2 ON T1.PK = T2.FOREIGNKEY
(INNER, FULL) JOIN (SELECT .. FROM table3) AS T3 ON T1.PK = T3.FOREIGNKEY
(INNER, FULL) JOIN (SELECT .. FROM table4) AS T4 ON T1.PK = T4.FOREIGNKEY
But if you can use lazy loading, no need use the Include() func. And lazy loading will solve your problem.
Other else, you can write with join query,
var query = from i in this.Items.Where(w=>demoIds.Contains(w.Id))
join d1 in demo1 on i.Id equals d1.FK
join d2 in demo2 on i.Id equals d2.FK
join d3 in demo3 on i.Id equals d3.FK
select new ... { };
This two solutions solve your all problems.
If it continues your problem, I strongly recommended store procedure.
I've got a similar issue with a query that had 15+ "Include" statements and generated a 2M+ rows result in 7 minutes.
The solution that worked for me was:
Disabled lazy loading
Disabled auto detect changes
Split the big query in small chunks
A sample can be found below:
public IQueryable<CustomObject> PerformQuery(int id)
{
ctx.Configuration.LazyLoadingEnabled = false;
ctx.Configuration.AutoDetectChangesEnabled = false;
IQueryable<CustomObject> customObjectQueryable = ctx.CustomObjects.Where(x => x.Id == id);
var selectQuery = customObjectQueryable.Select(x => x.YourObject)
.Include(c => c.YourFirstCollection)
.Include(c => c.YourFirstCollection.OtherCollection)
.Include(c => c.YourSecondCollection);
var otherObjects = customObjectQueryable.SelectMany(x => x.OtherObjects);
selectQuery.FirstOrDefault();
otherObjects.ToList();
return customObjectQueryable;
}
IQueryable is needed in order to do all the filtering at the server side. IEnumerable would perform the filtering in memory and this is a very time consuming process. Entity Framework will fix up any associations in memory.

Need help understanding how to convert sql statement to (Linq) or (Linq To SQL)

Hi I need some help coverting this sql statement to Linq, I am very new to Linq and LinqToSql, and this is my weakness, it seems like this is used frequently and I need to wrap my brain around the syntax. The Code is below.
select distinct t1.Color from [ProductAttributes] t1 join [Product] t2 on t1.Name = t2.ProductName where t1.ProductID = #productID order by t1.color
#productID is the parameter coming into the function, where I am trying to use Linq in MVC.
Thanks
It might be like this I guess
int myProductID = 1;//or whatever id you want.
MyDataContext mdc = new MyDataContext(CONNECTION_STRING_IF_NEEDED);
//MyDataContext is your datacontext generated by LinqToSql
var result = (from x in mdc.ProductAttributes
join y in Products on x.Name.equals(y.ProductName)
where x.ProductID = myProductID
orderby x.color
select x.Color).Distinct();
Note That Table names might need to be fixed.

Pagination with LINQ on Stored Procedures?

Is there a way where I can use something like the following code to paginate data without loading the whole data-set to the program?
var r = from c in entities.GetSearchData(null,"en",null,true) select c;
IPagedList<Models.SearchResult> results = r.ToPagedList<Models.SearchResult>(1, 10);
I'm trying to use a stored procedure with LINQ to get a paged result. (BTW the above code gives a "The result of a query cannot be enumerated more than once." error). Is it possible?
Can't test with Entity Framework at the moment, but the regular LINQ-to-SQL allows following statements:
var rpage1 = entities.GetSearchData(null,"en",null,true).Skip(0).Take(10)
var rpage2 = entities.GetSearchData(null,"en",null,true).Skip(10).Take(10)
var rlist = rpage1.ToList();
LINQ will generate a clause like
WHERE [t1].[ROW_NUMBER] BETWEEN #p0 + 1 AND #p0 + #p1
In my case the resulting query was (GetConstantsValues is a stored procedure):
SELECT [t1].[value] AS [Value]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[value]) AS [ROW_NUMBER], [t0].[value]
FROM [dbo].[GetConstantsValues](#p0) AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN #p1 + 1 AND #p1 + #p2
ORDER BY [t1].[ROW_NUMBER]
So only the relevant results are loaded into program.
I reckon, EF shouldn't differ much from it. May be wrong.
No need to go back to LINQ to SQL. There is a tweak that you can make. With entity framework, the result of a stored procedure is a collection of ObjectSet, hence the enumerations won't be allowed more than once, unless we convert it to a normal enumerable collection.
Simplest way to deal with such a case is as below,
var r = from c in entities.GetSearchData(null,"en",null,true) select c;
IPagedList<Models.SearchResult> results =
r.ToList().ToPagedList<Models.SearchResult>(1, 10);
Here r.ToList() makes the magic, and code would work without any hiccups!!
Note*: I know this is pretty old post, but thought of helping those who would come here looking for help!

How to loop in sql?

I dont want to use the "loop" related keyword, how can I implement loop with basic sql command in oracle ?
I have two table :
A:
ID, Color
B,
ID, AID, Type
I want to loop all records in B, and if ID = AID, then set the A.Color = B.Type
Thanks in advance !
Looping is, by definition, a procedural construct.
SQL is declarative: tell the database what you want done, not how to do it.
If you're absolutely convinced that you need to program such a thing, then write it in PL/SQL, Oracle's procedural language.
Bu I'm sure that it's possible to do what you want in SQL using an UPDATE with a WHERE clause.
Something like this (corrected per NullUserException):
UPDATE A SET A.Color = (SELECT B.Type FROM B WHERE A.ID = B.AID)
An alternate method:
MERGE INTO a
USING b
ON (b.aid = a.id)
WHEN MATCHED THEN UPDATE SET a.color = b.type;
You could just do:
UPDATE tablea a
SET a.color = (SELECT b.type
FROM tableb b
WHERE b.aid = a.id)
See this SQL script.
To do that you will have to write a stored procedure using PL/SQL. Here is the oracle page with some info and papers on the topic.
As others pointed out, you can probably solve your problem with a normal DML statement, without any looping involved. But to give you some basics on how to accomplish what you asked for in PL/SQL, here's an example...
DECLARE
CURSOR c IS
SELECT id, aid, type FROM b;
statement VARCHAR2(200);
BEGIN
FOR iterator IN c LOOP
IF iterator.id = iterator.aid THEN
statement := 'UPDATE a SET color = ' || iterator.type || 'WHERE id = ' || iterator.id;
EXECUTE IMMEDIATE statement;
END IF;
END LOOP;
END;
This anonymous PL/SQL block will iterate through each record in table b, and if b.id = b.aid, it will update table a and set a.color = b.type where a.id = b.id.
This seems to be what you were asking for. It's not exactly an efficient way to go about doing things, since you're firing off one DML statement per row in table b that has b.id=b.aid. But I wanted more to give this as a syntax example. This is just one way to iterate through a cursor by the way; you can also explicitly open cursors and fetch records, but it's easier this way if you don't need to do anything but iterate over the entire result set.

Linq to entities Left Join

I want to achieve the following in Linq to Entities:
Get all Enquires that have no Application or the Application has a status != 4 (Completed)
select e.*
from Enquiry enq
left outer join Application app
on enq.enquiryid = app.enquiryid
where app.Status <> 4 or app.enquiryid is null
Has anyone done this before without using DefaultIfEmpty(), which is not supported by Linq to Entities?
I'm trying to add a filter to an IQueryable query like this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where e.Applications.DefaultIfEmpty()
.Where(app=>app.Status != 4).Count() >= 1
select e);
Thanks
Mark
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Do this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where (!e.Applications.Any())
|| e.Applications.Any(app => app.Status != 4)
select e);
I don't find LINQ's handling of the problem of what would be an "outer join" in SQL "goofy" at all. The key to understanding it is to think in terms of an object graph with nullable properties rather than a tabular result set.
Any() maps to EXISTS in SQL, so it's far more efficient than Count() in some cases.
Thanks guys for your help. I went for this option in the end but your solutions have helped broaden my knowledge.
IQueryable<Enquiry> query = Context.EnquirySet;
query = query.Except(from e in query
from a in e.Applications
where a.Status == 4
select e);
Because of Linq's goofy (read non-standard) way of handling outers, you have to use DefaultIfEmpty().
What you'll do is run your Linq-To-Entities query into two IEnumerables, then LEFT Join them using DefaultIfEmpty(). It may look something like:
IQueryable enq = Enquiry.Select();
IQueryable app = Application.Select();
var x = from e in enq
join a in app on e.enquiryid equals a.enquiryid
into ae
where e.Status != 4
from appEnq in ae.DefaultIfEmpty()
select e.*;
Just because you can't do it with Linq-To-Entities doesn't mean you can't do it with raw Linq.
(Note: before anyone downvotes me ... yes, I know there are more elegant ways to do this. I'm just trying to make it understandable. It's the concept that's important, right?)
Another thing to consider, if you directly reference any properties in your where clause from a left-joined group (using the into syntax) without checking for null, Entity Framework will still convert your LEFT JOIN into an INNER JOIN.
To avoid this, filter on the "from x in leftJoinedExtent" part of your query like so:
var y = from parent in thing
join child in subthing on parent.ID equals child.ParentID into childTemp
from childLJ in childTemp.Where(c => c.Visible == true).DefaultIfEmpty()
where parent.ID == 123
select new {
ParentID = parent.ID,
ChildID = childLJ.ID
};
ChildID in the anonymous type will be a nullable type and the query this generates will be a LEFT JOIN.

Resources