I am using this example Linq code:
from objpath in _context.PathModel
join objOriginalStation in _context.StationModel
on objpath.IdStazioneOrigine equals objOriginalStation.IDStazione
join objDesttinationStation in _context.StationModel
on objpath.IdStazioneDestinazione equals objDesttinationStation.IDStazione
join objVia1Station in _context.StationModel
on objpath.IdVia1 equals objVia1Station.IDStazione
join objVia2Station in _context.StationModel
on objpath.IdVia2 equals objVia2Station.IDStazione
select new NewPercorsiModel
{
IdPercorso = objpath.IdPercorso,
IdSottorete = objpath.IdSottorete,
Distanza = objpath.Distanza,
IdStazioneDestinazione = objpath.IdStazioneDestinazione,
IdStazioneOrigine = objpath.IdStazioneDestinazione,
IdVia1 = objpath.IdVia1,
IdVia2 = objpath.IdVia2,
Versione = objpath.Versione ?? string.Empty,
StazioneOrigineName = objOriginalStation.NomeStazione,
StazioneDestinazioneName = objDesttinationStation.NomeStazione,
Via1Name = objVia1Station.NomeStazione,
Via2Name = objVia2Station.NomeStazione ?? string.Empty
};
First of all my question is that, have I a better solution to improve my code?
and second and important my question is that how could I check nullable for my objects(for example for objVia2Station) because when they are null I don't have all my records but I don't have any error also.
you can use "DefaultIfEmpty()" after each join like this code
from objpath in _context.PathModel
join objOriginalStation in _context.StationModel
on objpath.IdStazioneOrigine equals objOriginalStation.IDStazione into object1
from Ob1 in object1.DefaultIfEmpty()
join objDesttinationStation in _context.StationModel
on objpath.IdStazioneDestinazione equals objDesttinationStation.IDStazione into object2
from Ob2 in object2.DefaultIfEmpty()
join objVia1Station in _context.StationModel
on objpath.IdVia1 equals objVia1Station.IDStazione into object3
from Ob3 in object3.DefaultIfEmpty()
join objVia2Station in _context.StationModel
on objpath.IdVia2 equals objVia2Station.IDStazione into object4
from Ob4 in object4.DefaultIfEmpty()
select new NewPercorsiModel
{
IdPercorso = objpath.IdPercorso,
IdSottorete = objpath.IdSottorete,
Distanza = objpath.Distanza,
IdStazioneDestinazione = objpath.IdStazioneDestinazione,
IdStazioneOrigine = objpath.IdStazioneDestinazione,
IdVia1 = objpath.IdVia1,
IdVia2 = objpath.IdVia2,
Versione = Ob1.Versione ,
StazioneOrigineName = objOriginalStation.NomeStazione,
StazioneDestinazioneName = objDesttinationStation.NomeStazione,
Via1Name = objVia1Station.NomeStazione,
Via2Name = Ob4.NomeStazione
};
this code in equal to "Left Outer Join", But I don't like it because we can use Inheritance Strategy in Entity Framework
You should start receiving data when you encounter another table. like this:
var query = context.BaseTable.Select(x => new
{
x.Id,
x.field1,
x.field2,
..
..
alias_name= x.ForeignTable== null ? "" : x.ForeignTable.Name
});
Related
In my asp.net MVC application, view model I have created a property type string to display date.
But in the model, the property is stored as DateTime, so in my query, I have assigned the DateTime by converting it to ToShortDateString.
Because the value stored is with the DateTime in the table.(example2022-10-06 11:32:48.917)
But in the view, I just want to show the Date only.
When running this query I got this error
LINQ to Entities does not recognize the method 'System.String ToShortDateString()' method,
and this method cannot be translated into a store expression.'
Just want to know how to pass only the date to the view of this kind of query.
This is my current code.
var TaskMain = (from t in db.TaskMain
join service in db.Services on t.Service_Id equals service.Id
join category in db.ServiceCategory on service.Service_Category_Id equals category.Id
join branch in db.Branch on t.Current_Branch_Id equals branch.Id
join emp in db.Employee on t.Task_Assigned_Emp_Id equals emp.Id
where t.Id == id
select new TaskDetails
{
Id = t.Id,
Note = t.Note,
Current_Step= t.Task_Step_Id,
Service_Category = category.Service_Category_Name,
Service_End_Date = t.Service_End_Date.ToShortDateString(),
Service_Price = t.Service_Price,
Service_Start_Date = t.CreatedDate.ToShortDateString(),
Task_Created_Branch = branch.BranchName,
Service_Name = service.Service_NameEng
}).ToList();
ToShortDateString() is not something that the database recognize. So you need to bring the conversion to client side by using .AsEnumerable() (or .ToList()). Try this code.
var TaskMain = (from t in db.TaskMain
join service in db.Services on t.Service_Id equals service.Id
join category in db.ServiceCategory on service.Service_Category_Id equals category.Id
join branch in db.Branch on t.Current_Branch_Id equals branch.Id
join emp in db.Employee on t.Task_Assigned_Emp_Id equals emp.Id
where t.Id == id
select new
{
Id = t.Id,
Note = t.Note,
Task_Step_Id= t.Task_Step_Id,
Service_Category_Name = category.Service_Category_Name,
Service_End_Date = t.Service_End_Date,
Service_Price = t.Service_Price,
CreatedDate = t.CreatedDate,
BranchName = branch.BranchName,
Service_NameEng = service.Service_NameEng
}).AsEnumerable()
.Select(t => new TaskDetails
{
Id = t.Id,
Note = t.Note,
Current_Step= t.Task_Step_Id,
Service_Category = t.Service_Category_Name,
Service_End_Date = t.Service_End_Date.ToShortDateString(),
Service_Price = t.Service_Price,
Service_Start_Date = t.CreatedDate.ToShortDateString(),
Task_Created_Branch = t.BranchName,
Service_Name = t.Service_NameEng
}).ToList();
I have this query below. After that, I want to populate a list with the results. How should I do ?
var query = from cust in context.Customer
join city in context.Cities on cust.id_city equals city.id
join state in context.State on city.id_state equals state.id
join reg in context.Region on state.id_region equals reg.id
select new
{
nameCust = cust.name,
nameCity = city.name,
nameState = state.name,
nameRegion = reg.name
};
You should be able to call ToList() on the return value:
var queryResult = (from cust in context.Customer
join city in context.Cities on cust.id_city equals city.id
join state in context.State on city.id_state equals state.id
join reg in context.Region on state.id_region equals reg.id
select new
{
nameCust = cust.name,
nameCity = city.name,
nameState = state.name,
nameRegion = reg.name
}).ToList();
I'm wondering though, if you are using Entity Framework. If so: this might be a bether solution:
var queryResult = context.Customer
.Include(customer => customer.City)
.Include(customer => customer.State)
.Include(customer => customer.Region)
.ToList();
( ! ) Keep in mind you are loading a complete table into memory using ToList()
I'm using the entity framework and linq to do multiple left outer joins but it takes 3 seconds to run the query through the entity framework.
I used ((System.Data.Objects.ObjectQuery)query).ToTraceString(); and tested the sql statement in management studio and it executed instantly.
Here is the linq code.
var query = from Inventory in db.INVENTORies
join NewInventory in db.NEW_INVENTORY on Inventory.Barcode equals NewInventory.Barcode into lj_1
from q_NewInventory in lj_1.DefaultIfEmpty()
join Categories in db.Categorys on Inventory.CAT_ID equals Categories.CAT_ID into lj_2
from q_Categories in lj_2.DefaultIfEmpty()
join SCategories in db.StoneCategories on Inventory.TP_ID equals SCategories.TP_ID into lj_3
from q_SubCategory in lj_3.DefaultIfEmpty()
join qSupplier in db.Suppliers on Inventory.SUP_ID equals qSupplier.SUP_ID into lj_4
from q_Supplier in lj_4.DefaultIfEmpty()
join qStatus in db.Statuses on Inventory.ST_ID equals qStatus.ST_ID into lj_5
from q_Status in lj_5.DefaultIfEmpty()
join q_Locations in db.Locations on Inventory.LOC_ID equals q_Locations.LOC_ID into lj_7
from q_locations in lj_7.DefaultIfEmpty()
join q_Stone1 in db.Stones on Inventory.StoneID_1 equals q_Stone1.STONE_ID into lj_s1
from q_stone1 in lj_s1.DefaultIfEmpty()
join q_Stone2 in db.Stones on Inventory.StoneID_2 equals q_Stone2.STONE_ID into lj_s2
from q_stone2 in lj_s2.DefaultIfEmpty()
join q_Stone3 in db.Stones on Inventory.StoneID_3 equals q_Stone3.STONE_ID into lj_s3
from q_stone3 in lj_s3.DefaultIfEmpty()
join q_Stone4 in db.Stones on Inventory.StoneID_4 equals q_Stone4.STONE_ID into lj_s4
from q_stone4 in lj_s4.DefaultIfEmpty()
join q_Stone5 in db.Stones on Inventory.StoneID_5 equals q_Stone5.STONE_ID into lj_s5
from q_stone5 in lj_s5.DefaultIfEmpty()
join q_Stone6 in db.Stones on Inventory.StoneID_6 equals q_Stone6.STONE_ID into lj_s6
from q_stone6 in lj_s6.DefaultIfEmpty()
join q_Stone7 in db.Stones on Inventory.StoneID_7 equals q_Stone7.STONE_ID into lj_s7
from q_stone7 in lj_s7.DefaultIfEmpty()
join q_Stone8 in db.Stones on Inventory.StoneID_8 equals q_Stone8.STONE_ID into lj_s8
from q_stone8 in lj_s8.DefaultIfEmpty()
join qMasterInventory in db.MASTERINVENTORies on q_NewInventory.InvItemNo equals qMasterInventory.INVITEMNO into lj_6
from q_MasterInventory in lj_6.DefaultIfEmpty()
where Inventory.Barcode == _Barcode
select new
{
inv_InvID = Inventory.INV_ID, inv_Barcode = Inventory.Barcode,
inv_catID = Inventory.CAT_ID, inv_SubCatID = Inventory.TP_ID, inv_Price = Inventory.ITEM_PRICE, inv_Cost = Inventory.ITEM_COST,
inv_PricePoint = Inventory.PricePoint, inv_StatusID = Inventory.ST_ID, inv_StID = Inventory.ST_ID, inv_SupID = Inventory.SUP_ID,
inv_LocID = Inventory.LOC_ID, inv_LabSupplier = Inventory.LabSupplier, inv_LabStone1 = Inventory.LabStone1, inv_LabCategory = Inventory.LabCategory,
inv_LabExtra = Inventory.LabExtra, inv_LabMadeIn = Inventory.LabMadeIn, inv_Width = Inventory.ChainThickNess, inv_Size = Inventory.ChainSize,
inv_Stone1 = Inventory.StoneID_1,inv_Stone2 = Inventory.StoneID_2,inv_Stone3 = Inventory.StoneID_3,inv_Stone4 = Inventory.StoneID_4,inv_Stone5 = Inventory.StoneID_5,inv_Stone6 = Inventory.StoneID_6,inv_Stone7 = Inventory.StoneID_7,inv_Stone8 = Inventory.StoneID_8,inv_Stone9 = Inventory.StoneID_9,inv_Stone10 = Inventory.StoneID_10,
stat_Status = q_Status.DESCRIPTION,
cat_Category = q_Categories.DESCRIPTION,
subCat_SubCategory = q_SubCategory.DESCRIPTION,
sup_Supplier = q_Supplier.Name,
loc_Location = q_locations.DESCRIPTION,
mas_SKU = q_MasterInventory.INVITEMNO,
mas_GUID = q_MasterInventory.ItemGUID,
stone1 = q_stone1.DESCRIPTION,
stone2 = q_stone2.DESCRIPTION,
stone3 = q_stone3.DESCRIPTION,
stone4 = q_stone4.DESCRIPTION,
stone5 = q_stone5.DESCRIPTION,
stone6 = q_stone6.DESCRIPTION,
stone7 = q_stone7.DESCRIPTION,
stone8 = q_stone8.DESCRIPTION,
};
Create database view for this query and map the view to new read only entity. After that compare differences between pure LINQ execution and a new execution. If the problem was with converting your terrible LINQ query to SQL you will avoid it by using this approach. If it is still slow the problem will be elsewhere.
Guys in comments said that you have to re-write it in T-SQL. True. You can try one of SQL to LINQ converter tools.
Also use MS SQL Profiler to see what happens and improve TSQL performance.
Try to add indexes but not too much :)
I have a beginners LINQ2SQL question. I have this huge (but not complex) SQL statement:
SELECT Artikel.ArtikelID,
Artikel.CategorieID,
Artikel.ImageFile,
Artikel.RetailPrijs,
ISNULL(ShopArtikel.VerkoopsPrijs, Artikel.VerkoopsPrijs) AS VerkoopsPrijs,
Artikel.ArtikelCode,
Artikel.InAssortimentSinds,
ArtikelTaal.ArtikelNaam,
ArtikelTaal.ArtikelOmschrijving
FROM Artikel
INNER JOIN ArtikelTaal ON Artikel.ArtikelID = ArtikelTaal.ArtikelID
INNER JOIN ShopArtikel ON Artikel.ArtikelID = ShopArtikel.ArtikelID
INNER JOIN Categorie ON Artikel.CategorieID = Categorie.CategorieID
INNER JOIN CategorieTaal ON Categorie.CategorieID = CategorieTaal.CategorieID
INNER JOIN Shop ON ShopArtikel.ShopId = Shop.ShopID
INNER JOIN CategorieGroepShop ON Shop.ShopID = CategorieGroepShop.ShopId
INNER JOIN Taal ON ArtikelTaal.TaalCode = Taal.TaalCode AND CategorieTaal.TaalCode = Taal.TaalCode
INNER JOIN CategorieGroepTaal ON Taal.TaalCode = CategorieGroepTaal.TaalCode AND CategorieGroepShop.CategorieGroepId = CategorieGroepTaal.CategorieGroepID
INNER JOIN CategorieGroep ON Categorie.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepTaal.CategorieGroepID = CategorieGroep.CategorieGroepID AND CategorieGroepShop.CategorieGroepId = CategorieGroep.CategorieGroepID
WHERE (Shop.ShopID = 23) AND
(Taal.TaalCode = 'dut') AND
(Artikel.Onzichtbaar = 0) AND
(Artikel.NietBestelbaar = 0) AND
(Categorie.Onzichtbaar = 0) AND
(Artikel.Voorraad >= Artikel.LevertijdDrempel)
and I am converting this to LINQ and have this:
var allProducts = from artikelen in dc.Artikels
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join catg in dc.CategorieGroeps on cat.CategorieGroepID equals catg.CategorieGroepID
join catgt in dc.CategorieGroepTaals on catg.CategorieGroepID equals catgt.CategorieGroepID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catgt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
where sh.ShopID == shop.BLL.Business.ShopController.CurrentShop.Id
select dc.Artikels;
but I have the idea that I made some (minor) mistakes while joining.
any ideas please!
EDIT
I have rewritten the LINQ query to this:
var allProducts = from artikelen in dc.Artikels
join at in dc.ArtikelTaals on artikelen.ArtikelID equals at.ArtikelID
join sa in dc.ShopArtikels on artikelen.ArtikelID equals sa.ArtikelID
join cat in dc.Categories on artikelen.CategorieID equals cat.CategorieID
join catt in dc.CategorieTaals on cat.CategorieID equals catt.CategorieID
join sh in dc.Shops on sa.ShopId equals sh.ShopID
join catgs in dc.CategorieGroepShops on sh.ShopID equals catgs.ShopId
join tl in dc.Taals on new { tc1 = at.TaalCode, tc2 = catt.TaalCode } equals new { tc1 = tl.TaalCode, tc2 = tl.TaalCode }
join catgt in dc.CategorieGroepTaals on new { tl.TaalCode, catgs.CategorieGroepId } equals new { catgt.TaalCode, catgt.CategorieGroepID }
join catg in dc.CategorieGroeps on new { cat.CategorieGroepID, catgt.CategorieGroepID, catgs.CategorieGroepId } equals new { catg.CategorieGroepID, catg.CategorieGroepID, catg.CategorieGroepID }
where sh.ShopID == 230
select dc.Artikels;
but I have a syntax error after "dut" }
Edit 2:
changed the join and replaced "dut" with the corresponding field in the database.
still have the error after the first }
it says: type inference failed in the call to 'Join'
Some of the SQL joins have multiple join conditions, which you didn't put in the LINQ query.
If this is something that will be frequently run then you should rewrite it as a stored procedure. I believe it is too convoluted and complex for a LINQ statement - too hard to see what's going on.
There is a tool for it, but I didn't try it. May be it's usefull for you.
http://www.sqltolinq.com/
It looks like the error line is actually a "Where" cause but not "Joining".
You can actually split the whole long Linq statement into smaller Query.
so for this case, its better to split it like this:
var at = from a in dc.ArtikelTaals
where a.TaalCode == "dut"
select a;
var catt = from c in dc.CategorieTaals
where c.TaalCode == "dut"
select c;
.....
and you can join the IQueryable "at" and "catt" in your complex query later.
I am trying to write a query that grabs information from one database and joins it to information in a different database.
TableA
idA
valueA
idB
TableB
idB
valueB
The tricky part is that in TableA, idB isn't always defined, so when I do a normal join, I only get results where TableA has a idB value. What I want is to be able to grab all of the information from TableA even if it doesn't have a corresponding idB value.
Here is a query expression syntax version of the left join to follow up on tvanfosson's answer.
var query = from rowA in db.TableA
join rowB in db.TableB
on rowA.idB equals rowB.idB into b
from item in b.DefaultIfEmpty()
select new
{
idA = rowA.idA,
valueA = rowA.valueA,
idB = rowA.idB,
valueB = item != null ? item.valueB : 0 // or other default value
};
Use a left outer join by checking if the value returned from the right hand side is null and supplying a default value for that case.
var q = db.TableA.Join( db.TableA,
a => a.idB,
b => b.idB,
(a,b) => new
{
A = a.ValueA,
B = b == null ? null : b.ValueB
});
You can do a left outer join in LINQ with SelectMany (directly calling Queryable methods) or in comprehension syntax join ... into:
var results = from a in db.TableA
join b in db.TableB on a.idB equals b.idB
into found
select new {
A = a,
Bs = found
};
In the output Bs will be IEnumerable<typeof-db-TableB>
Left Join Example:
var leftOuterJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID into prodGroup
from item in prodGroup.DefaultIfEmpty(new Product{Name = String.Empty, CategoryID = 0})
select new { CatName = category.Name, ProdName = item.Name };