Join table in Entity framework - c#

I'll have this query in joining the table but it did not returned data from Include table or Join table.
var tasks = (from item in ctx.Tasks
join tp in ctx.TaskPlugins
on item.TaskId equals tp.TaskId
select item)
.Include(x => x.TaskPlugins).Include(x => x.TaskPlugins.Select(p => p.Plugin)).Include(x=>x.TaskPlugins.Select(p=>p.Plugin.Store));
return ctx.Tasks.ToList();
But this query does not return data from TaskPlugins
Error Message: ((System.Data.Entity.DynamicProxies.Task_6F777A6C52D9E84FD3DF53481564A61969CE62ABBA9D985448F99BFB8A49A2D7)new System.Collections.Generic.Mscorlib_CollectionDebugView<oRouter.Model.Task>(task).Items[0]).TaskPlugins
Thanks.

One thing, You should be returning tasks.ToList() and not ctx.Tasks.ToList()
Second, the last include .Include(x=>x.TaskPlugins.Select(p=>p.Plugin.Store) is the only one needed. First 2 includes are NOT needed.

Related

C# & Entity Framework : return specific columns from a 3 table join

I have a C# application where I am using Entity Framework to pull data from a database. This is the code I am executing:
var person = new List<Person>();
using (DevTestEntities db = new DevTestEntities())
{
person = (from p in db.People
join e in db.PersonEmails on p.Id equals e.Id
join t in db.PersonPhones on p.Id equals t.Id
where t.Phone == phoneNumber
select p).ToList();
}
var str = Newtonsoft.Json.JsonConvert.SerializeObject(person);
return str;
When the code runs, it fails on the select. I assume it is failing because there is a table within the database that is not part of the model. And because there is just a generic select, I assume Entity Framework is selecting all columns from all tables and doesn't know what to do with some of the columns.
What I really want to do is to be able to specify the columns that I want to return to the calling function. How do I specify what columns Entity Framework should select?
Thanks for any assistance.
EF will not fail because of tables in the DB that are not in model. It would help if you provided the error. Also, your query will result in selecting all columns from the People table but not the others.
An example answer to your question is this, it selects three columns from different tables and puts them in a new anonymous type:
var onlySomeColumns = (from p in db.People
join e in db.PersonEmails
on p.Id equals e.Id
join t in db.PersonPhones
on p.Id equals t.Id
where t.Phone == phoneNumber
select new {p.Id, e.email, t.phonenumber}).ToList();

Group data and retrieve every line of the grouping with Entity Framework

I was thinking that maybe, once the grouped data are retrieved in the C# part, I would be able loop through the list of items that were grouped.
var res = db.Commandes.Where(t => t.idMatiere == mod.idMatiereChoisie).GroupBy(t => t.UA_idCa);
foreach(var group in res)
{
foreach(var groupedLines in group)
{
// Always a single line, this loop is useless
}
}
It seems the logic applied here is more like SQL than C#: the grouping result in a single line and you won't see all the grouped items.
It's not a problem that I can't overcome
Tactic I will use: instead of grouping, I'll just query all the lines, and then, while looping, I will verify if UA_idCa is different form the previous data and that will means the next "group" has been reached.
But I wonder... How does someone normally do this cleanly, if it's possible?
Do you have to query again to retrieve a group's content?
Or is the "Tactic I will use" closer to what's best?
This problem is a matter of the combination of SQL server AND Entity Framework.
Seems like one of the value in the grouped part (a value that is different for all the line inside the group) must be marked as not null.
Because when looking for what could be a key, entity doesn't give a damn about nullable values : they could be unique, they could be never null, EF won't even check that.
Once it is marked as NOT NULL in the sql part, EF suddenly understand that there could multiple different unique values in the grouped part...
So basically This :
ALTER view [dbo].[Commandes] as
SELECT top(50000000)
isnull(ex.unitAdm, '000') UnitAdm
,c.id as idCahier
,isnull(ex.unitAdm, '000') + cast(c.id as nvarchar(6)) as UA_idCa
,c.NomCahier
,[Qte]
,c.prix as PrixCahier
,sc.id, 0 as idSousCahier /* THIS IS WHAT I COULD NOT COMPLETELY RETRIEVE
because it could be null ? */
,sc.NomCahier as sousCahier
,sc.prix as PrixSC
,m.id as idMatiere
,m.Code
,m.NomMatiere
,ep.id as idEpreuve
,ep.Titre
FROM [CahierExamen] cex
join Cahier c on c.id = cex.Fk_Cahier
join Examen ex on cex.FK_Examen = ex.id
join epreuve ep on ex.FK_Epreuve = ep.id
join Matiere m on ep.FK_Matiere = m.id
left join SousCahier sc on c.id = sc.FK_Cahier
order by code, unitAdm, idCahier
GO
As been changed to this:
ALTER view [dbo].[Commandes] as
SELECT top(50000000)
isnull(ex.unitAdm, '000') UnitAdm
,c.id as idCahier
,isnull(ex.unitAdm, '000') + cast(c.id as nvarchar(6)) as UA_idCa
,c.NomCahier
,[Qte]
,c.prix as PrixCahier
,isnull(sc.id, 0) as idSousCahier /* WOW, NOW EF UNDERSTAND
THERE COULD BE MULTIPLE DIFFERENTS VALUES ONCE DATA ARE GROUPED*/
,sc.NomCahier as sousCahier
,sc.prix as PrixSC
,m.id as idMatiere
,m.Code
,m.NomMatiere
,ep.id as idEpreuve
,ep.Titre
FROM [CahierExamen] cex
join Cahier c on c.id = cex.Fk_Cahier
join Examen ex on cex.FK_Examen = ex.id
join epreuve ep on ex.FK_Epreuve = ep.id
join Matiere m on ep.FK_Matiere = m.id
left join SousCahier sc on c.id = sc.FK_Cahier
order by code, unitAdm, idCahier
GO

how to get the max value of id from second table using join in entity framework in asp.net c#

I have two tables, from 1st table i want to get all records and from 2nd table i want the max id value of that record. I am using entity framework in asp.net c#.
i tried the below code but it takes only single record from first table i.e tblblogs. and leave all the records, how to get all those records by using this query? plz help me out I'll be very grateful to you. Thanks !
var query= (from c in db.tblBlogs join a in db.tblBlogMedias on c.id
equals a.BlogId where c.id==db.tblBlogMedias.Max(p=>p.id)
select new
{}
If I understood, you want to get an object with specific fields of Blogs and a list of tblBlogMedias.
You could try this code:
var query2 = (from c in db.tblBlogs
orderby c.Id descending
group c.tblBlogMedias by new { c.Id, c.Name } into gb //It will show Id and name of tblBlogs, you can use more fields if you want
select new {
Id = gb.Key.Id,
Name = gb.Key.Name, //I don't know if you have this field, but you should change it
SecondTable = gb.ToList()
})
.OrderByDescending(o => o.Id) //this orderby with FirstOrDefault() replace where c.id==db.tblBlogMedias.Max(p=>p.id)
.FirstOrDefault();

Linq return distinct values from table if not exist in another

I am trying to return all distinct rows from Staging below where Staging.CenterCode does not exist in Centers.CenterCode.
At the moment Stagings has around 850 distinct CenterCodes and Centers is empty so I should be getting all of the distinct rows, but count begs to differ :)
Any ideas?
var query =
(from s in db.Stagings
join t in db.Centers on s.CenterCode equals t.CenterCode into tj
from t in tj.DefaultIfEmpty()
where s.CenterCode != t.CenterCode
select s.CenterCode).Distinct();
var c = query.Count();
I only need the unique columns from staging so not sure if I actually need a join with the above as I am not ever using data returned from Centers - I have however tried both and get the same 0 value for count.
Any ideas?
I would not use a join, but use a Contains.
var centerCodesQuery = db.Centers.CenterCode
.Select(x => x.CenterCode);
var query = db.Staging
.Where(x => !centerCodesQuery.Contains(x.CenterCode))
.Select(x => x.CenterCode)
.Distinct();
var c = query.Count();
the join is an inner join. So, if none of the rows in 1 table match the other table on the specified identifier then it will return 0. In yours you are trying to join 1 table with 850 distinct rows with an empty table. This will return 0.
If you actually want to return only those rows in 1 table that aren't in another you can use Except:
var query = (from s in db.Stagings
select s.CenterCode)
.Except(from t in db.Centers
select t.CenterCode);
var c = query.Count();
Looks like you are trying to implement antijoin via left outer join, which is one of the possible ways, but in order to make it work, you need to change
where s.CenterCode != t.CenterCode
to
where t == null

NHibernate: How to eager fetch sub entities with a filter over sub entity through one sql query without lazyload?

I'am using NHibernate 3.3.1 with FluentNhibernate 1.3 for Data Layer.
I have the following entities:
Database Diagram:
I need a method that gets the Products by MediaCategory of Medias of Products. I want NHibernate to send only one query to db and fetch all sub properties of products.
I want NHibernate send a query like this:
declare #mediaCategoryId int = 13
select *
from Product p
inner join Media m on m.ProductId=p.Id
inner join MediaCategoryMedia mcm on mcm.MediaId=m.Id
inner join MediaCategory mc on mc.Id=mcm.MediaCategoryId
left join ProductSeller ps on ps.ProductId=p.Id
left join Seller s on ps.SellerId=s.Id
where mc.Id=#mediaCategoryId
I have tried the following options to solve this challenge;
session.QueryOver< ProductEntity >()...
I have tried Inner.JoinQueryOver< .. >().Fetch.Eager... but I couldn't fetch all the sub entities.
session.CreateCriteria< ProductEntity >().SetFetchMode("",FetchMode.Eager)...
In this case lazy load works and I dont want lazyload. If I disable lazyload from mappings NH sends lots of queries.. what I want is eager load with one single query that fetches all sub entities.
session.Query< ProductEntity >().FetchMany(p=>p.MediaList).ThenFetchMany(m=>m.SellerList)...
I couldn't create alias to pass mediaCategoryId filter in this case. Instead I used .Where(x=>x.MediaList.Any(m=>m.CategoryList.Any(...))) and the query generated is not optimum, too.
(from p in session.Query< ProductEntity >()
from m in p.MediaList
from c in m.MediaCategoryList
where c.Id==23
select p).Fetch(x=>x.MediaList);
this didn't work as I wanted, too..
var hql=#"select p from ProductEntity as p join fetch p.MediaList as m join fetch m.MediaCategoryList as mc left join fetch p.SellerList as s where mc.Id=:catId ";
THIS WORKS with "join fetch" in hql.
I need the best practice of this case, however Hql is the king.
Can we handle this case with session.Query<>() or session.CreateCriteria, or QueryOver ?
For a direct translation of your query...
Media mediaAlias = null;
MediaCategory categoryAlias = null;
return session.QueryOver<Product>()
.JoinAlias(x => x.Medias, () => mediaAlias)
.JoinAlias(() => mediaAlias.Categories, () => categoryAlias)
.Fetch(x => x.Sellers).Eager
.Where(() => categoryAlias.Id == mediaCategoryId)
.List();
JoinAlias does an inner join by default, and Fetch(...).Eager does a left outer join. JoinAlias allows us to dig down through Media to the categories, and it also eagerly fetches the data.
Note that there is a Cartesian product between Sellers and Medias in this query. If there are 20 Medias and 20 Sellers on a single Product, then this query would return 20 * 20 = 400 rows, which is not ideal for performance. You can address this by splitting the Media fetching and the Seller fetching into separate queries, but batch them together in one round-trip to the database using Future(), meaning the query would return 20 + 20 = 40 rows. Much better.
Also, this query will not return all of the categories associated with a Media. If you need this, then you should apply the mediaCategoryId constraint in an Exists sub-query.

Categories