Entity Framework - Select * from Entities where Id = (select max(Id) from Entities) - entity-framework

I have an entity set called Entities which has a field Name and a field Version. I wish to return the object having the highest version for the selected Name.
SQL wise I'd go
Select *
from table
where name = 'name' and version = (select max(version)
from table
where name = 'name')
Or something similar. Not sure how to achieve that with EF. I'm trying to use CreateQuery<> with a textual representation of the query if that helps.
Thanks
EDIT:
Here's a working version using two queries. Not what I want, seems very inefficient.
var container = new TheModelContainer();
var query = container.CreateQuery<SimpleEntity>(
"SELECT VALUE i FROM SimpleEntities AS i WHERE i.Name = 'Test' ORDER BY i.Version desc");
var entity = query.Execute(MergeOption.OverwriteChanges).FirstOrDefault();
query =
container.CreateQuery<SimpleEntity>(
"SELECT VALUE i FROM SimpleEntities AS i WHERE i.Name = 'Test' AND i.Version =" + entity.Version);
var entity2 = query.Execute(MergeOption.OverwriteChanges);
Console.WriteLine(entity2.GetType().ToString());

Can you try something like this?
using(var container = new TheModelContainer())
{
string maxEntityName = container.Entities.Max(e => e.Name);
Entity maxEntity = container.Entities
.Where(e => e.Name == maxEntityName)
.FirstOrDefault();
}
That would select the maximum value for Name from the Entities set first, and then grab the entity from the entity set that matches that name.

I think from a simplicity point of view, this should be same result but faster as does not require two round trips through EF to sql server, you always want to execute query as few times as possible for latency, as the Id field is primary key and indexed, should be performant
using(var db = new DataContext())
{
var maxEntity = db.Entities.OrderByDecending(x=>x.Id).FirstOrDefault()
}
Should be equivalent of sql query
SELECT TOP 1 * FROM Entities Order By id desc
so to include search term
string predicate = "name";
using(var db = new DataContext())
{
var maxEntity = db.Entities
.Where(x=>x.Name == predicate)
.OrderByDecending(x=>x.Id)
.FirstOrDefault()
}

I think something like this..?
var maxVersion = (from t in table
where t.name == "name"
orderby t.version descending
select t.version).FirstOrDefault();
var star = from t in table
where t.name == "name" &&
t.version == maxVersion
select t;
Or, as one statement:
var star = from t in table
let maxVersion = (
from v in table
where v.name == "name"
orderby v.version descending
select v.version).FirstOrDefault()
where t.name == "name" && t.version == maxVersion
select t;

this is the easiest way to get max
using (MyDBEntities db = new MyDBEntities())
{
var maxReservationID = _db .LD_Customer.Select(r => r.CustomerID).Max();
}

Related

How to use Dynamic query in linq to entites?

I am using linq to entites and I want to use the dynamic query in it?
is it possible?
var datas = (from u in _context.Users
where u.AlfId == 25
select new
{
u.Id,
UpdatedByUserName = "select * from dbo.abc(u.Id)"
}
).OrderByDescending(m => m.Id).ToList();

Compare two arrays in LINQ query

I want to write LINQ query to compare two arrays. I want the query to be translated to the following query:
SELECT id, name
FROM persons
WHERE '{"dance", "acting", "games"}' && (hobbies);
That condition work in that way:
'{"dance"}' && '{"dance", "acting", "games"}'; -- true
'{"dance","singins"}' && '{"dance", "acting", "games"}'; -- true
'{"singins"}' && '{"dance", "acting", "games"}'; -- false
I wrote this query:
List<string> arr = new List<string>(){ "dance", "acting", "games" };
var query = (from p in _context.Persons
where arr.Any(kw => p.hobbies.Contains(kw))
select new
{
id = p.id,
name = p.name
}).ToList();
The translated query is:
SELECT p."id" AS id, p."name" AS name
FROM dataBase."Persons" AS p
It can understand that the filter performs in the server. so the query brings all the data from DB and filtered on the server. This causes to performance problems and not pass Load-Testing.
I need a query that will not only do the job but will also be translated to the above query with '&&'.
Is there any way in LINQ to execute this query?
Thanks
If your database looks similar like I am predicting this could be a solution. Some more code though but I think this should be executed as a SQL IN statement:
List<string> arr = new List<string>(){ "dance", "acting", "games" };
var matches = from hobby_person in _context.Hobbies_Persons
join person in _context.Persons on person.Id equals hobby_person.PersonId
join hobby in _context.Hobbies on hobby.Id equals hobby_person.HobbyId
where arr.Contains(hobby.Name)
select new
{
id = p.id,
name = p.name
}).ToList();

Entity framework returning incorrect data from columns with same name

I have a few tables in my database which are mapped to an edmx. Using the entity framework to return data from these tables, I've encountered a problem where the value in the "name" column from one of my higher level data models is being populated into each model below it.
I'm pulling the data like this:
var query = (from a in context.things
where a.id == 1
select a);
var model = query.Select(a => new modelA()
{
Name = a.name,
Bs = a.Bs.Select(b => new modelB()
{
Name = b.name,
Cs = b.Cs.Select(c => new modelC()
{
Name = c.name,
Ds = c.Ds.Select(d => new modelD()
{
Name = d.name
})
})
})
}).FirstOrDefault();
b.name, c.name and d.name are all returning the same value as a.name despite my database definitely having different values in across these tables.
Could this be a caching issue?
Update
After upgrading the mySql connector to the latest version (6.7.4.0) I am still encountering the error.
After the upgrade it seems i can get 3 levels deep before the data in the name column starts reappearing :(

EF Left joining a table on two properties combined with a case statement

I'm trying to write a query for a database that will left join a table to a look up table and the results will be returned based on a case statement.
In normal SQL the query would look like this:
SELECT chis_id, chis_detail, cilt.mhcatID, cilt.mhtID, 'TheFileName' =
CASE
WHEN cilt.mhcatID IS NOT NULL AND cilt.mhtID IS NOT NULL THEN chis_linked_filename
END
FROM chis
LEFT JOIN cilt on cilt.mhcatID = chis.mhcat_id AND cilt.mhtID = chis.mht_id
WHERE cch_id = 50
chis is the table being queried, cilt is a look-up table and does not contain any foreign key relationships to chis as a result (chis has existing FK's to mht and mhcat tables by the mhtID and mhcatID respectively).
The query will be used to return a list of history updates for a record. If the join to the cilt lookup table is successful this means that the caller of the query will have permission to view the filename of any associated files for the history updates.
Whilst during my research I've found various posts on here relating on how to do case statements and left joins in Linq to Entity queries, I've not been able to work out how to join on two different fields. Is this possible?
You need to join on an anonymous type with matching field names like so:
var query = from x in context.Table1
join y in context.Table2
on new { x.Field1, x.Field2 } equals new { y.Field1, y.Field2 }
select {...};
A full working example using the an extra from instead of a join would look something like this:
var query = from chis in context.Chis
from clit in context.Clit
.Where(x => x.mhcatID = chis.mhcat_id)
.Where(x => x.mhtID = chis.mht_id)
.DefaultIfEmpty()
select new
{
chis.id,
chis.detail,
cilt.mhcatID,
cilt.mhtID,
TheFileName = (cilt.mhcatID != null && cilt.mhtID != null) ? chis.linked_filename : null
};
Based on what Aducci suggested, I used a group join and DefaultIsEmpty() to get the results I wanted. For some reason, I couldn't get DefaultIfEmpty() didn't work correctly on its own and the resulting SQL employed an inner join instead of a left.
Here's the final code I used to get the left join working:
var query = (from chis in context.chis
join cilt in context.cilts on new { MHT = chis.mht_id, MHTCAT = chis.mhcat_id } equals new { MHT = cilt.mhtID, MHTCAT = cilt.mhcatID } into tempCilts
from tempCilt in tempCilts.DefaultIfEmpty()
where chis.cch_id == 50
select new {
chisID = chis.chis_id,
detail = chis.chis_detail,
filename = chis.chis_linked_filename,
TheFileName = (tempCilt.mhcatID != null && tempCilt.mhtID != null ? chis.chis_linked_filename : null),
mhtID = chis.mht_id,
mhtcatID = chis.mhcat_id
}).ToList();

Converting T-SQL to Linq

I am using Entitry Framework 4.1 and I am struggling to understand how the convert the below query which uses joins and aggregate methods to a Linq to Entities call in the DomainService.
SELECT tblTime.Period As Timeline, COUNT(tblEngineeringDashboard_ItemList.ID) AS Items
FROM tblEngineeringDashboard_ItemList INNER JOIN
tblTime ON tblEngineeringDashboard_ItemList.TimeID = tblTime.ID
GROUP BY tblTime.Period
ORDER BY tblTime.Period
Can anyone provide help.
Possible Solution
Dim var = From i In ObjectContext.tblEngineeringDashboard_ItemList
Join t In ObjectContext.tblTimes On i.TimeID Equals t.ID
Group By i.TimeID Into Group
Select DateStart = (From n In ObjectContext.tblTimes Where n.ID = TimeID Select n.Period), PartCount = Group.Count
Phil
The first thing which comes to mind is:
var q = from t in Context.Time
group t by t.Period into g
orderby g.Key
select new
{
Timeline = g.Key,
Items = (from ti in g
from il in ti.ItemList // or whatever the property for the navigation to tblEngineeringDashboard_ItemList is called
select il).Count()
};
However, the original SQL had an INNER JOIN, which would reject tblTime records without any matching records in tblEngineeringDashboard_ItemList. So you may want:
var q = from t in Context.Time
where t.ItemList.Any()
group t by t.Period into g
orderby g.Key
select new
{
Timeline = g.Key,
Items = (from ti in g
from il in ti.ItemList // or whatever the property for the navigation to tblEngineeringDashboard_ItemList is called
select il).Count()
};
You can also flip the query around:
var q = from i in Context.EngineeringDashboardItemList
where i.Time != null
group i by i.Time.Period into g
orderby g.Key
select new
{
Timeline = g.Key,
Items = g.Count()
};
Does this work?
tblEngineeringDashboard_ItemList
.Join(tblTime,ed => ed.TimeID ,t => t.ID, (ed,t) => new{ed,t})
.GoupBy(g => g.t.Period)
.Select(s => new
{
Timeline = s.Key,
Items = s.Count()
}
)
.OrderBy(o => o.Timeline)
While converting from sql to linq isn't an ideal approach (you should think directly in linq, translating your need to a linq query), the query you posted is rather simple.
var grouped = tblTime.OrderBy(c => c.Period).GroupBy(c => c.Period).Select(c =>
new {
timeline = c.Key,
count = c.SelectMany(x => x.tblEngineeringDashboard).Count()
});
*Edit: There, fixed. Everything on the L2E engine.
This provided that there are correct foreign keys between the tables (thus you don't have to declare the join manually).