In EF7 there is a new ExecuteUpdate function to do updates on a table without retrieving the data from the server first.
Is it possible to do an update from select with this method in any way where it is using data from another table?
To be more concrete can i express this SQL in EF:
UPDATE
Table_A
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
FROM
Some_Table AS Table_A
INNER JOIN Other_Table AS Table_B
ON Table_A.id = Table_B.id
WHERE
Table_A.col3 = 'cool'
The following query updates table with values from joined table.
var query =
from a in context.TableA
join b in context.TableB on a.id equals b.id
where a.col3 == "cool"
select new { a, b };
query.ExecuteUpdate(s =>
s.SetProperty(x => x.a.col1, x => x.b.col1)
.SetProperty(x => x.a.col2, x => x.b.col2)
);
Related
I have 3 simple tables (entities): Page (id), Control (id, page_id) and Setting (id, control_id).
So the structure is Page->Control->Setting.
I have query:
SELECT
p.*
,c.*
,s.*
FROM #page p
LEFT JOIN ( SELECT * FROM #control WHERE id = #controlid) c ON p.id = c.page_id
LEFT JOIN ( SELECT * FROM #settings WHERE id = #settingid) s ON s.id = c.page_id
WHERE
p.id = #pageid
How to build NHibernate construction to generate the same query?
If your datamodel is correct you would only have to do something like this
session.QueryOver<Page>()
.Fetch(x => x.Control)
.Eager.List<Page>();
Depending on a lot of thins you may have to implement ThenFetch.
SELECT * FROM register WHERE user_id LIKE 'a%'
SELECT * FROM register WHERE user_id LIKE '%m'
SELECT * FROM register WHERE user_id LIKE '%andru%'
SELECT R.name,C.country_name,S.state_name
FROM register R JOIN country C ON R.country_id=C.country_id
JOIN state S ON R.state_id=S.state_id
SELECT R.name,C.country_name,S.state_name
FROM register R INNER JOIN country C ON R.country_id=C.country_id
INNER JOIN state S ON R.state_id=S.state_id
Now i need LinqToSql Queries instead of these query
var result = context.Registers.Select(x => x.StartsWith(foo)).ToList();
result = context.Registers.Select(x => x.EndsWith(foo)).ToList();
result = context.Registers.Select(x => x.Contains(foo)).ToList();
result = from register in context.Registers
join state in context.States on register.state_id equals state.state_id
select new { register.name, state.country_name, state.state_name }
Note, inner join and join function the same in SQL — thus no need to complicate.
T-SQL:
declare #postlocations table (locationid int)
insert into #postlocations
select locationid
from dbo.PostLocations
where PostId = 162172
select t.*
from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
LINQ-Entities i have so far:
var postLocations = e.SomePost.Locations; // pre-fetched, e.g materialized ICollection<Post>
var themes = (from t in db.Themes
join q in postLocations on t.Locations.Select(l => l.LocationId) equals q.LocationId
select t).ToList();
But the compiler is complaining on the join keyword about not being able to infer the type arguments.
Any ideas?
I don't think you can join a SQL table with an in-memory list of objects, even if those objects are originally from the database.
Convert the in-memory list of objects to a list of id's (integer), and use that in the join or in a Contains/sub-select. EF can translate the list of id's to parameters when generating the SQL.
The problem with your join is that you're implying a collection of LocationId (t.Locations.Select(l => l.LocationId) can equal a single LocationId. You're trying to join a Theme which has a collection of Locations onto a single Location.
You should be able to fix this by using Contains
var themes = (from t in db.Themes
join q in postLocations
on t.Locations.Select(l => l.LocationId).Contains(q.LocationId)
select t).ToList();
or if EF complains about passing a postLocations as a parameter, you can try
// I'd materialize this but you may not have to
var postLocationIds = postLocations.Select(p => p.LocationId).ToList();
var themes = db.Themes.Where(t => t.Locations.Any(l =>
postLocationIds.Contains(l.LocationId))).ToList();
Edit
how about this
///your sql query
select t.* from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
//linq query for that
from t in teams
join from tl in teamlocation on t.themid = tl.ThemeID
join from pl in postlocation on tl.temeid = pl.temeid
select t;
Org
Not sure but you can try out by using let keyword
var themes = (from t in db.Themes
let location = t.Locations
join q in postLocations on location.LocationId equals q.LocationId
select t).ToList();
I have a many to many relationship between tables A and B.
Since I used code first, the DB table 'AB' was automatically created. I don't have an entity model for it.
How can I, for example, query all the B's that belong to A.id=x?
Edit:
After I load either A or B, I can easily get references to lists B and A respectively.
My real problem is making a single query that excludes all B's that are already associated with A.
This is what I want to do:
query.Where(**b.ID NOT IN (SELECT B.ID FROM AB WHERE A=5)** )
I'm sure I could do this with a raw sql query, but I want to be consistent and use IQueryable/LINQ where I can.
You can try this:
var bsNotAssociatedWithA5 = context.Bs
.Where(b => !b.As.Any(a => a.Id == 5))
.ToList();
It creates the following SQL:
SELECT
[Extent1].[BId] AS [BId],
[Extent1].[BColumn1] AS [BColumn1],
// more columns
FROM [dbo].[Bs] AS [Extent1]
WHERE NOT EXISTS
(SELECT 1 AS [C1]
FROM [dbo].[ABs] AS [Extent2]
WHERE ([Extent1].[BId] = [Extent2].[BId]) AND (5 = [Extent2].[AId]))
Edit
When using DbContext (EF >= 4.1) you can inspect the SQL by using ToString() of the IQueryable:
var bsNotAssociatedWithA5Query = context.Bs
.Where(b => !b.As.Any(a => a.Id == 5));
string sql = bsNotAssociatedWithA5Query.ToString();
var bsNotAssociatedWithA5 = bsNotAssociatedWithA5Query.ToList();
A.Bs
If you have an instance of A you should have a property in the A class to retrive all the B-s from A.
I have a Category table with a tree structure (Id,MasterId)
I'd like to select all products that belong to a Category and all Child Categories.
Today I use this SQL Query which works, but I'd like to add pagination and that would be easier with a pure LINQ query. I use Entity Framework 4.
#Count int = 100,
#CategoryId int
with mq as
(
select c.Id as parent, c.Id as child
from dbo.Categories c
where c.Id = #CategoryId
union all
select q.child, c.Id
from mq q
inner join dbo.Categories c on q.child = c.MasterId
)
select top (#Count) P.* from Products P
inner join ProductToCategory PC ON(PC.ProductId = P.Id)
where PC.CategoryId in (
select child from mq
)
and P.PublishStatus = 1
order by P.PublishedDate DESC;
Any ideas how to get a nice LINQ query on this with pagination (current page, number of products per page, total product count)?
This is recursive / hiearchical query with table expression. EF does not provide support for such queries. If you want to receive data by single roundtrip to DB you must wrap it in stored procedure and import that procedure to your entity framework model.
Paging in SQL is also possible when using table expressions and ROW_NUMBER().
there is an idea. i haven't tested it, so dont blame if it doesn't work :P
var ids = context.TreeItems.Where(x => x.Id == parentId).Select(x => (int?)x.Id);
var tmp = ids;
while (true)
{
IQueryable<int?> localIds = tmp;
var subIds = context.TreeItems.Where(x => ids.Contains(x.ParentId)).Select(x => (int?)x.Id);
if (subIds.Any())
{
tmp = subIds;
ids = ids.Union(subIds);
}
else
break;
}
var allSubItems = context.TreeItems.Where(x => ids.Contains(x.Id));