one-to-many with Default - c#

I have News. One news can have many Tags, Categories and Images. Special for it i thing about extended model.
public class NewsExt
{
public News News { get; set; }
public List<Categories> Categories { get; set; }
public List<Images> Images { get; set; }
public List<Tags> Tags { get; set; }
}
or
public class NewsExt
{
public Base.News News { get; set; }
public Categories Categories { get; set; }
public Images Images { get; set; }
public Tags Tags { get; set; }
}
I work with second variant and want something like this:
return
((from n in db.News
from i in db.Images.DefaultIfEmpty()
from t in db.Tags.DefaultIfEmpty()
from c in db.Categories.DefaultIfEmpty()
select new NewsExt()
{
News = n,
Images = i,
Tags = t,
Categories = c
}).GroupBy(news => news.News))
I want *Array of NewsExt** with one News and all other entities without repeating in each element of this array.
For the first viewmodel I try:
(from n in db.News
select new NewsExt()
{
News = n,
Images = (from i in db.Images.DefaultIfEmpty()
from n_i in db.News_Image
where n_i.news_id == n.id
select i).ToList(),
Tags = (from t in db.Tags.DefaultIfEmpty()
from n_t in db.News_Tag
where n_t.news_id == n.id
select t).ToList(),
Categories = (from c in db.Categories.DefaultIfEmpty()
from n_c in db.News_Category
where n_c.news_id == n.id
select c).ToList()
}).ToList();
But have excess records.

I decide to use first viewmodel.
(from n in db.News
select new NewsExt()
{
News = n,
Images = (from i in db.Images.DefaultIfEmpty()
join n_i in db.News_Image on i.id equals n_i.image_id
where n_i.news_id == n.id
select i).ToList(),
Tags = (from t in db.Tags.DefaultIfEmpty()
join n_t in db.News_Tag on t.id equals n_t.tag_id
where n_t.news_id == n.id
select t).ToList(),
Categories = (from c in db.Categories.DefaultIfEmpty()
join n_c in db.News_Category on c.id equals n_c.category_id
where n_c.news_id == n.id
select c).ToList()
}).ToList();

Related

LINQ uses extra inner join

Here are my simplified models:
public class Resource
{
public int id { get; set; }
public string Name { get; set; }
}
public class Upgrade
{
public int Id { get; set; }
public virtual Resource Res { get; set; }
public int Lvl { get; set; }
public int Amount { get; set; }
}
Basically, I need to group by Resource and get [Name] from "Resource" and sum([Amount]) from "Upgrade".
Here is the LINQ:
from u in _db.Upgrades
join r in _db.Resources on u.Res equals r
where u.Lvl > levelFrom
&& u.Lvl <= levelTo
group u by new { r.id, r.Name } into grp
select new UpgradeCost()
{
resName = grp.Key.Name,
resAmount = grp.Sum(k => k.Amount),
};
And here is the SQL I get (Sqlite):
SELECT "r0"."Name" AS "resName", COALESCE(SUM("u"."Amount"), 0) AS "resAmount"
FROM "Upgrades" AS "u"
LEFT JOIN "Resources" AS "r" ON "u"."Resid" = "r"."id"
INNER JOIN "Resources" AS "r0" ON "r"."id" = "r0"."id"
WHERE ("u"."Lvl" > #__levelFrom_0) AND ("u"."Lvl" <= #__levelTo_1)
GROUP BY "r0"."id", "r0"."Name"
LINQ uses extra INNER JOIN to group by.
I want it to be made like this:
SELECT "r"."Name" AS "resName", COALESCE(SUM("u"."Amount"), 0) AS "resAmount"
FROM "Upgrades" AS "u"
LEFT JOIN "Resources" AS "r" ON "u"."Resid" = "r"."id"
WHERE ("u"."Lvl" > #__levelFrom_0) AND ("u"."Lvl" <= #__levelTo_1)
GROUP BY "r"."id", "r"."Name"
Additional join generated when used u.Res navigation property. Actually you don't need explicit joins here.
from u in _db.Upgrades
where u.Lvl > levelFrom
&& u.Lvl <= levelTo
group u by new { u.Res.id, u.Res.Name } into grp
select new UpgradeCost()
{
resName = grp.Key.Name,
resAmount = grp.Sum(k => k.Amount),
};

LINQ to a model including List

I would like to get your advice on Linq.
I have 3 tables users ( listing all the users), another one userEtablishments (one user can have many places), and the table Establishment (to list the place)
i have a models which is:
public class UserVM {
public Int32 id { get; set; }
public string name { get; set; }
public List<Etablishment> Etablishments { get; set; }
}
and the Etablishment:
public class EtablishmentVM {
public Int32 id { get; set; }
public string name { get; set; }
}
I query first the users, then establishments of the user, but its very slow:
UserVM obj = new UserVM();
using (context db = new context(ConnectionString))
{
userlist = (from u in db.users
join p in db.establishments on u.id equals p.id
join pe in db.userEtablishments on p.id equals pe.id
select new
{
u,
}).FirstOrDefault();
if (entity != null)
{
obj.id = entity.u.id);
obj.name = entity.u.name);
// Then get the establishment list then update the establishmentVM
List<EstablishmentVM> userplaces = new List<EstablishmentVM>();
var userplacesList = (from u in db.users join p in db.establishments on
u.id equals p.id join pe in db.userEtablishments on p.id equals pe.id
select new { u, pe }).ToList();
if (userplacesList != null && userplacesList.Count > 0)
{
foreach (var item in userplacesList)
{ }.....
is there a better way to do to get it execute faster ?
Any advices would helps, the purpose is to get betterperformances.
Thanks for your helps

Linq - Join where ID's !=, select new + distinct?

I have the following classes.
Course;
public class Course
{
//pk
public int Id{ get; set; }
public int SourceCourseId { get; set; }
public string Name { get; set; }
}
Registration
public class Registration
{
//primary key
public int Id { get; set; }
//...more fields
public int CourseId { get; set; }
}
I want to obtain a collection of annonymous objects with the two fields below for all Courses that are Distinct in the registrations table that are not in the Courses table.
var distinctCourses = (from registration in db.Registrations
join courses in db.Courses on registration.CourseId equals courses.SourceCourseId
where registration.CourseId != courses.SourceCourseId
select new
{
SourceCourseId = registration.CourseId,
Name = registration.CourseName,
}).Distinct().ToList();
For some reason the above is returning 0... Any suggestions?
try a left join:
var query = from r in registrations
join c in courses on r.CourseId equals c.id into newCourses
from nullCourse in newCourses.DefaultIfEmpty()
where nullCourse == null
select new { }
Edit - per comment from Alex :
Also, your where clause needs to change to
where nullCourse == null
Edit - changed join columns and added correct where clause.
Edit - group registrations on CourseID so they will be distinct
var distinctCourses =
(from registration in db.Registrations
group registration by registration.CourseId into grp
from reg in grp
join courses in db.Courses on reg.CourseId equals courses.SourceCourseId into newCourses
from nullCourse in newCourses.DefaultIfEmpty()
where nullCourse == null
select new
{
SourceCourseId = reg.CourseId,
Name = reg.CourseName,
}).ToList();
Try this
var result = Registrations.GroupJoin(Courses,r=>r.CourseId,c=>c.SourceCourseId,
(k,g) => new {k,g})
.Where(x=>x.g.Count()==0)
.Select(s=> new {id=s.k.CourseId,name=s.k.CourseName});

Recursively select all child ids and join in one string using Linq

I have a category model look like this:
public class Category
{
public int Id { get; set; }
public int ParentCategoryId { get; set; }
public string ChildIDs { get; set; }
}
I want to Recursively select all child ids and join in ChildIDs like this: 12,13,17,31
This is my Linq query, but it returns 1 level childern:
from cg in db.Categories
where cg.Id == id
join urc in
(from x in db.UrlRecords where x.EntityName == "Category" select x) on cg.Id equals urc.EntityId into urccg
from f in urccg.DefaultIfEmpty()
select new
{
cg,
f,
ParentCategoryId = cg.ParentCategoryId,
ChildIds = string.Join(",", (from x in db.Categories where x.ParentCategoryId == cg.Id select x.Id))
}

Linq query to return list within a list

Hi I have following two model classes
public class c1
{
public int id { get; set; }
public int ptId { get; set; }
public int bId { get; set; }
public int rId { get; set; }
public IEnumerable<styles> newStruct { get; set; }
}
public class styles
{
public int id { get; set; }
public int bId { get; set; }
public string desc { get; set; }
}
I am trying to write a linq query
var records = (from y in db.main
join c in db.secondary on y.bId equals c.bId
where c.id == id
select new c1
{
pId= c.pId,
id = c.id,
newStruct = new List<styles>
{
new styles
{
id=y.room_id,
desc=y.desc,
}
}
});
return records.ToList();
Problem I am having is that in newStruct is suppose to be List of all the styles but it just returns one style at a time rather than one list.
Please let me know how can it return record where inside it contains list of styles
Thanks
If you want to get a sublist by main list, you should use group by,
You can try this, but I'm not sure it worked. Becasue I couldn't compile it.
var records = (from y in db.main
join c in db.secondary on y.bId equals c.bId
where c.id == id
group c by new
{
c.pId,
c.id
} into gcs
select new c1
{
pId = c.Key.pId,
id = c.Key.id,
newStruct = from g in gcs select new styles { id=g.room_id, desc=g.desc}
});
Is this LINQ to Entities? If so, and the mappings are correct in the edmx, you can try:
var records =
from c in db.secondary
where c.id == id
select new c1
{
pId = c.pId,
id = c.id,
newStruct = c.main.Select(m => new styles { id = m.room_id, desc = m.desc })
};
return records.ToList();

Categories