Search ranking in LINQ, MVC 3 and Entity Framework - asp.net-mvc

Previously in SQL I would use something like this to rank my search results:
--search product name
SELECT tblProduct.ProductID, 20 AS Ranking
FROM tblProduct
INNER JOIN tblManufacturer ON tblProduct.ManufacturerID=tblManufacturer.ManufacturerID
LEFT OUTER JOIN tblProductCollection ON tblProduct.CollectionID=tblProductCollection.CollectionID
WHERE tblManufacturer.Name + ISNULL(' ' + tblProductCollection.CollectionName, '') + ' ' + tblProduct.Name LIKE '%' + #term + '%' AND tblProduct.Active = 1
UNION ALL
--search product exact name
SELECT tblProduct.ProductID, 200 AS Ranking
FROM tblProduct WHERE Name = '%' + term AND tblProduct.Active = 1
UNION ALL
This example says if your search term is contained in the name: 20 is the rank, if you match the name exactly: 200 is the rank. Union the tables together, order by Ranking(descending) and hey presto!
I'm trying to do this in LINQ this time round and am unsure how to go about doing it, to be honest I'm unsure my previous example was the best way to do it originally.
So, I have a Product Entity mapped to my database and I've added a property in my partial class called SearchRanking:
var query = from p in db.Products
where p.Name.Contains(term)
select p;
var query2 = from p in db.Products
where p.Name.ToLower() == term
select p;
Somehow I need to set the properties like so:
var query = from p in db.Products
where p.Name.Contains(term)
select p, p.SearchRanking = 20;
var query2 = from p in db.Products
where p.Name.ToLower() == term
select p, p.SearchRanking = 200;
Am I on the right track?

If you're wanting to create a new anonymous type you could do this:
var foundProducts = (from p in products
where p.Name.Contains(term)
select new Product
{
ProductId = p.ProductId,
Category = p.Category,
Brand = p.Brand,
SearchRanking = p.Name.ToLower() == term ? 200 : 20
}).OrderBy(s => s.SearchRanking).Take(20);

I would do something like this;
var query = (from p in db.Products
where p.Name.Contains(term)
select p).ToList().ForEach(p => p.SearchRanking = 20);
A more efficient way would be to;
var query = (from p in db.Products
where p.Name.Contains(term)
select new Product
{
Id = p.Id,
//set the other props here
SearchRanking = 20
}).ToList();

Related

Applying where condition to each value selected in Linq query with Groupby in it

In this linq query I need to apply where condition for selecting only tiertype .I have tried the following but getting error in the where condition of tiertype.The error is "ti in ti.ImageVersion ti does not exist in current context.
var result = (from p in _context.Product
join ti in _context.TierImageMap on p.Id equals ti.ProductId
join t in _context.Tiers on ti.TierType equals t.Id
where (p.Id == productname)
orderby ti.ReleaseVersion descending
group new { ti, t } by new { ti.ImageName, t.TierType,ti.ImageVersion } into cities
select new
{
ReleaseVersion = string.Join(",", (from n in cities select n.ti.ReleaseVersion).Distinct().Take(3)),
ImageName = string.Join(",", (from n in cities select n.ti.ImageName).Distinct()),
TierType = string.Join(",", (from n in cities select n.t.TierType).Where(ti.ImageVersion== imageversion).Distinct())
//String.Format(ti.ReleaseVersion, ", ").GroupBy.OrderByDescending( ti.ImagDESeName ) as Releaseversion,
//String.Format(t.TierType, ", ").GroupBy.OrderByDescending( ti.ImageName ) as Tiertype
}).ToList().Distinct();
await _context.SaveChangesAsync();

How to use group by with multiple table joins in Entity framework core

I am trying to convert below query in entity framework core but not able to access field in select query after apply group by.
Select ProdCatg.Category As [Category]
,Prod.FKProdCatgID As [FKProdCatgID]
,SUM(Dtl.Qty + LD.ProdConv1 + Trn.CashAmt ) As [DistributionRateValue]
From tblSalesInv_Dtl Dtl
Left Join tblSalesInv_Trn Trn on Trn.PKID=Dtl.FKID And Trn.FKSeriesID=Dtl.FKSeriesID
Left Join tblProdLot_Dtl LD on Dtl.FKLotID=LD.PKLotID And LD.FKProdID=Dtl.FKProdID
Left Join tblProd_Mas Prod ON PKProdID=Dtl.FKProdID
Left Join tblProdCatg_Mas ProdCatg On PKProdCatgID=Prod.FKProdCatgID
Where Trn.DraftMode=0
Group By Prod.FKProdCatgID,ProdCatg.Category
Order By Category
I am trying convert like this but but not able to access Dtl.Qty + LD.ProdConv1 + Trn.CashAmtfields
var result1 = (from dtl in _context.TblSalesInvDtl
join ser in lstSeries on dtl.FkseriesId equals ser
join trn in _context.TblSalesInvTrn on new { s1 = dtl.Fkid, s2 = ser } equals new { s1 = trn.Pkid, s2 = trn.FkseriesId }
join lot in _context.TblProdLotDtl on new { s1 = dtl.FklotId, s2 = dtl.FkprodId } equals new { s1 = lot.PklotId, s2 = lot.FkprodId }
join p in _context.TblProdMas on dtl.FkprodId equals p.PkprodId into pr
from Prod in pr.DefaultIfEmpty()
join pl in _context.TblProdMas on dtl.FklinkedProdId equals pl.PkprodId into plid
from ProdLinked in plid.DefaultIfEmpty()
join t in _context.TblTaxMas on dtl.FktaxId equals t.PktaxId into tid
from Tax in tid.DefaultIfEmpty()
join c in _context.TblProdCatgMas on Prod.FkprodCatgId equals c.PkprodCatgId into cid
from Catg in cid.DefaultIfEmpty()
where trn.EntryDate == Convert.ToDateTime("1-12-2018")
group Catg by new { Prod.FkprodCatgId, Catg.Category } into gb
//, dtl, lot, Prod
select new
{
CategoryName = gb.FirstOrDefault().Category,
DistributionRateValue = gb.Sum(a => (gb.Key.dtl.Qty + gb.Key.lot.ProdConv1+ gb.Key.lot.CashAmt)),
FKProdCatgID= gb.Key.Prod.FkprodCatgId,
}
).ToList();
can anybody help me how can I access multiple table fields in sum with groupby in entity framework core.

how return multiple column in join result to view model

I want to return multiple column in join result and fill in view model(VMFoodFoodMeal).
for example I want to fill VMFoodFoodMeal by Join result
Thanks
IEnumerable<VMFoodFoodMeal> _fmt = (from e in db.FoodProgramMealFood
join j in db.Foods on e.FoodId equals j.Id
select new
{
Id = e.Id,
Name = j.Name,
});
It is hard to understand what you want, but as example you can look here at Group Join section.
Here is an example code from there:
public void Linq103()
{
string[] categories = new string[]{
"Beverages",
"Condiments",
"Vegetables",
"Dairy Products",
"Seafood" };
List<Product> products = GetProductList();
var q =
from c in categories
join p in products on c equals p.Category into ps
select new { Category = c, Products = ps };
foreach (var v in q)
{
Console.WriteLine(v.Category + ":");
foreach (var p in v.Products)
{
Console.WriteLine(" " + p.ProductName);
}
}
}
result:
Beverages:
Chai
Chang
Guaraná Fantástica
Sasquatch Ale
Steeleye Stout
Côte de Blaye
Chartreuse verte
Ipoh Coffee
...
if you want to send your join Result to a model without using foreach statement you have to use this code
IEnumerable<VMFoodFoodMeal> _fmt = (from e in db.FoodProgramMealFood
join j in db.Foods on e.FoodId equals j.Id
select new VMFoodFoodMeal()
{
Id = e.Id,
Name = j.Name,
});
for example in above code I had a view model (VMFoodFoodMeal) and want to fill it by join result.
I have to make new instance of my model in select and then fill its property.
Thanks

Nested query in Linq

I have three tables. I have to retrieve the data using Linq statement. My three table names are A,B,C. I connected join for connecting two tables A and B based on the id's like:
select ol, fN, LN, ci, co
from member
join details
on member_id = details_id
where details_id in
(select contacts_id from contacts where
contacts_id1 = 1 and contacts_usr_id = 1)
I am able to write the query up to the where condition, how can I write the query for the inner while condition?
you can try this:
var idlist = (from tbl in table3
where tbl.usr_id == 1 && tbl.contacts_id == 1
select tbl.contacts_id ).ToList();
var x = from A in table1
from B in table2 where A.user_id == B.user_id
&& idlist.Contains(A.user_id)
select new { a = A.a, b = A.b, c = A.c, d = B.d, e = B.e };
check and let me know if that work.
Try flipping the query upside down. How about the following:
var query =
from t3 in table3
where t3.user_id = 1 && t3.contacts_id = 1
join t2 in table2 on t3.contacts_id equals t2.usr_id
join t1 in table1 on t2.usr_id equals t1.userid
select new {t2.a, t2.b, t2.c, t1.d, t1.e};

EF 4.0 Linq to Enity query

Hi guys i need to replicate this SQL query in Linq to Entity
select * from Subscriber a
inner join User b on a.UserId = b.Id
where b.Username = 'Name'
May be some one may help.
Try this:
var query = from s in context.Subscribers.Include("User")
where s.User.Username == "Name"
select s;
This suppose that Subscriber has navigation property User referencing the user instance.
If you wan to use join (which is not needed) you can use this for inner join:
var query = from s in context.Subscribers
join u in context.Users on s.User.Id equals u.Id
where u.Username == "Name"
select new
{
Subscriber = s,
User = u
};
or this for left outer join:
var query = from s in context.Subscribers
join u in context.Users on s.User.Id equals u.Id into x
where u.Username == "Name"
from y in x.DefaultIfEmpty()
select new
{
Subscriber = s
User = y,
};

Resources