How to get distinct value from the list - entity-framework-4

I have a List generated from Linq to Entities query. In which, I need to get a unique records based on BibId. I have tried changing the query but no help to get the unique records based on BibId.
Query
aa.NewBibContentsModel = (from x in db.BibContents
where (x.TagNo == "245" && x.NormValue == aa.CurrentTitle) || (x.TagNo == "020" && x.NormValue == aa.CurrentISBN) || (x.TagNo == "022" && x.NormValue == aa.CurrentISBN)
select new
{
BibId = x.BibId,
Title = (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == "245" orderby a.Id ascending select a.NormValue),
//Tit = (from a in db.BibContents where a.BibId == line.BibId && a.TagNo == "245" && a.Sfld == "a" select a.NormValue).FirstOrDefault(),
Author = (from a in db.BibContents where a.BibId == x.BibId && splitted.Contains(a.TagNo) && a.NormValue != null select a.TagNo).FirstOrDefault(),
ISBN = (from a in db.BibContents where a.BibId == x.BibId && a.NormValue != null && (a.TagNo == "020" || a.TagNo == "022") orderby a.Id ascending select a.NormValue)
}).AsEnumerable().Select(x => new BibContentsModel
{
BibId = x.BibId,
Title = string.Join(" ", x.Title),
Author = string.Join(" ", (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == x.Author orderby a.Id select a.NormValue)),
ISBN = string.Join(" ", x.ISBN)
}).ToList();
Any help to this problem will be appreciated.
Thanks

What you're trying to achieve is know as Distinct By. MoreLinq has a function for it. The syntax would look like:
(from x in db.BibContentsNo == "022")
... // your query
}).AsEnumerable()
.DistinctBy(x => x.BibId) // <= MoreLinq
What is does is group the records by BibId and take the first element of each group.
You can download MoreLinq as a NuGet package.

Related

Converting Sql to Linq (to Entities)

I have a query like that and it works normally. If a student gets more than one course, it list all of them:
SELECT ks.KullaniciKodu as username, ks.Sifre as password, k.adi as firstname, k.soyadi as lastname, k.Email as email,
MAX(CASE WHEN c.DERSKODU = 'ENF100' THEN 'ENF100' ELSE '' END)As course1,
MAX(CASE WHEN c.DERSKODU = 'ATA101' THEN 'ATA101' ELSE '' END) As course2,
MAX(CASE WHEN c.DERSKODU = 'TDB101' THEN 'TDB101' ELSE '' END) As course3,
MAX(CASE WHEN c.DERSKODU = 'İNG101' THEN 'İNG101' ELSE '' END) As course4
FROM Kayit k
JOIN DersNotu dn ON dn.KayitNo = k.KayitNo
JOIN Ders c ON c.DersKayitNo = dn.DersKayitNo AND c.DERSKODU IN ('ENF100','ATA101','TDB101', 'İNG101') AND c.DONEM = '201512'
JOIN KullaniciSifre ks ON ks.KullaniciKodu = k.KullaniciKodu
GROUP BY ks.KullaniciKodu, ks.Sifre, k.adi, k.soyadi, k.Email
But when i convert it to Linq (to Entity), it only gets one course or all courses are null. Where is the difference and problem in this code?
from k in db.Kayit
join dn in db.DersNotu on k.KayitNo equals dn.KayitNo
join c in db.Ders on dn.DersKayitNo equals c.DersKayitNo
join ks in db.KullaniciSifre on k.KullaniciKodu equals ks.KullaniciKodu
where
(new string[] { "ENF100", "ATA101", "TDB101", "İNG101" }).Contains(c.DersKodu) &&
c.Donem == 201512
group new { ks, k, c } by new
{
ks.KullaniciKodu,
ks.Sifre,
k.Adi,
k.Soyadi,
k.Email
} into g
select new
{
KullaniciKodu = g.Key.KullaniciKodu,
Sifre = g.Key.Sifre,
Adi = g.Key.Adi,
Soyadi = g.Key.Soyadi,
Email = g.Max(p => (
p.k.Email == string.Empty ? "NULL" : p.k.Email)),
Course1 = g.Max(p => (
p.c.DersKodu == "ENF100" ? "ENF100,1" : "NULL,1")),
Course2 = g.Max(p => (
p.c.DersKodu == "ATA101" ? "ATA101,1" : "NULL,1")),
Course3 = g.Max(p => (
p.c.DersKodu == "TDB101" ? "TDB101,1" : "NULL,1")),
Course4 = g.Max(p => (
p.c.DersKodu == "İNG101" ? "İNG101,1" : "NULL,1"))
}
Using MAX in SQL is just a trick to work-around the problem. You should not convert that explicitly to LINQToEntity. The problem here is you use Max against strings. In your case the NULL,1 seems be always selected as max except for the TDB101,1.
The actual logic here is such as for ENF100, if any one found, project for "ENF100", otherwise project for "NULL,1". The same logic for others. So it should be like this:
Course1 = g.Any(p => p.c.DersKodu == "ENF100") ? "ENF100,1" : "NULL,1",
Course2 = g.Any(p => p.c.DersKodu == "ATA101") ? "ATA101,1" : "NULL,1",
Course3 = g.Any(p => p.c.DersKodu == "TDB101") ? "TDB101,1" : "NULL,1",
Course4 = g.Any(p => p.c.DersKodu == "İNG101") ? "İNG101,1" : "NULL,1"
Also the Email is projected wrong, it is already included in the group key, so you can just project it via the group key:
Email = g.Key.Email

Lambda not in like SQL

I’m working with MVC 5 and I’m quite new on it. How can convert the below sql code to lambda expression. Basically what I’m trying to do is to show all records that ProductID not exist in Scrap Table
Select * from Product
where ProductID not in (Select ProductID from Scrap where ref = '123')
and active = 1
I believe your query is equivalent to:
select p.*
from Product p
join Scrap s on p.ProductID = s.ProductID
where
s.ref <> '123'
and p.active = 1
If so, try this:
from p in db.Products
join s in db.Scraps on p.ProductID equals s.ProductID
where s.Ref != "123" && p.Active == 1
select p
Try
var query =
from p in db.Products
where !(from s in db.Scrap
where s.ref == '123'
select s.ProductId)
.Contains(p.ProductId)
&& p.Active = 1
Try something like:
var products = (from p in db.Products //db is an instance of my datacontext
where !db.Scrap.Any(s => s.ProductId == p.ProductId && s.ref == "123")
&& p.active == 1 // p.active == true if active is of type bit in sql
select p);

How to find the data between month in entityframework?

I had requirement to display the data of this month (between month starting to ending data )
I know how to do in MySQL below query
enter code here select #MonthAmount := IFNULL(sum(AmountReceived), 0.0) as TotoalAmountperMonth
from collection
where date_time between DATE_FORMAT(NOW() ,'%Y-%m-01')
and LAST_DAY(now() - interval 0 month ) and AgentID=v_agent) as monthamount
but how to do using entity (lambda expression) I am new to entity when I google I got to get the data of today but in month?
below query got the result of today data
enter code here var newAuctionsResults = repo.FindAllAuctions()
.Where(a => a.IsActive == true
|| (a.StartTime.Value.Year == todayYear
&& a.StartTime.Value.Month == todayMonth
&& a.StartTime.Value.Day == todayDay))
.ToList();
Try
DateTime date = DateTime.Today;
var newAuctionsResults = repo.FindAllAuctions()
.Where(a => a.StartTime.Value.Year == date.Year
&& a.StartTime.Value.Month == date.Month)

Return Original datatype after LINQ group by

I need my LINQ Query to return the Product Datatype, after being grouped. It seems to be encased into an anonymous psuedo family.
I have some properties in Product that I don't care about, just needing the p.ID and p.Name etc.
The error I'm getting at the moment with this is:
The entity or complex type 'DatabaseModel.Product' cannot be constructed in a LINQ to Entities query.
This is my Method:
public static List<Product> GetSellableSpecialOffers(DatabaseEntities db)
{
var query = from p in db.Products
where (p.Visible == true && p.Active == true)
&& p.ShowInSpecialOffers == true
group p by p.FamilyID == null ? 0 : p.FamilyID into f
select new Product {
ID = f.First().ID,
Name = f.First().Name,
Cost = f.First().Cost,
RRP = f.First().RRP
};
return query.ToList();
}
What is the problem? Is there a better way around this? SQL would always return 1 record instead of encasing the object in a secondary datatype, I don't get it.
Many thanks,
EDIT 1:
My apologies for extending the specification, but I need the returned product to be programatically generated e.g.
select new Product {
ID = f.First().ID,
Name = f.First().Name,
Cost = f.OrderBy(p => p.NowCost).FirstOrDefault(),
RRP = f.First().RRP
}
or if I could strongly type the family class:
public partial class ProductFamily
{
public Product GroupedProduct
{
get
{
return this.Products.OrderBy(p => p.NowCost).FirstOrDefault();
}
}
}
Then I would do:
var query = (from p in db.Products
where (p.Visible == true && p.Active == true)
&& p.ShowInSpecialOffers == true
group p by p.ProductFamily == null ? null : p.ProductFamily into f
select f.GroupedProduct).ToList<Product>();
But I can't get either solution to work with what I have.
You can try (boring, but not sure you have the choice)
var query = from p in db.Products
where (p.Visible == true && p.Active == true)
&& p.ShowInSpecialOffers == true
group p by p.FamilyID == null ? 0 : p.FamilyID into f
select new {
ID = f.First().ID,
Name = f.First().Name,
Cost = f.OrderBy(m => m.NowCost).First().Cost,
RRP = f.First().RRP
};
return query.ToList().Select(m =>
new Product {
ID = m.ID,
Name = m.Name,
Cost = m.Cost,
RRP = m.RRP
};
EDIT
Or as pointed by Master Skeet (not exactly the same as what you tried, but much easier)
var query = from p in db.Products
where (p.Visible == true && p.Active == true)
&& p.ShowInSpecialOffers == true
group p by p.FamilyID == null ? 0 : p.FamilyID into f
select f.OrderBy(m => m.NowCost).First();
You could simply select f.First() and return the resulting data, like this:
var query = from p in db.Products
where (p.Visible == true && p.Active == true)
&& p.ShowInSpecialOffers == true
group p by p.FamilyID == null ? 0 : p.FamilyID into f
select f.First();
Then outside the method use whatever properties you need, ignoring what you don't care about (you are handling Product objects, properties should be there even if you don't need them).
Remove the word 'Product' from
select new Product{}
'select new' itself will create an anonymous type whereas you are specifying it as a Product.

asp.net mvc datettime linq check for empty

var postsidebar = from post in postrepository.GetAllPosts()
join pstmt in postrepository.GetAllPostMetas()
on post.int_PostId equals pstmt.int_PostId
where (post.int_PostTypeId == 4
&& post.int_PostStatusId == 2
&& post.int_OrganizationId == layoutrep.GetSidebarDetailById(SidebarDetailsId).int_OrganizationId)
&& (pstmt.vcr_MetaKey.Contains(filter) && pstmt.vcr_MetaValue.Contains("true")
&& (System.DateTime.Now >=
Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
select post;
how can i check for empty in this part in Date(it is giving error)
&& (System.DateTime.Now >= Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
You could try eliminated the possibility of an empty value first and then try your cast afterward.
&& pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date"
&& !string.IsNullOrEmpty(m.vcr_MetaValue))
&& (System.DateTime.Now >=
Convert.ToDateTime(pstmt.Post.PostMetas.FirstOrDefault(m =>
m.vcr_MetaKey == "Publish Date").vcr_MetaValue)))
Try this:
// declare the action for re-use
Func<PostMeta,bool> action = m => m.vcr_MetaKey == "Publish Date";
// then test for Any() before comparing anything
&& (pstmt.Post.PostMetas.Any(action) && System.DateTime.Now >= Convert.ToDateTime(pstmt.Post.PostMetas.First(action).vcr_MetaValue)))

Resources