How to group rows using LINQ to Entity separating values with commas? - c#

Below is my LINQ Query, that im using to select ITEMS:
protected void Page_Load(object sender, EventArgs e)
{
whatsmydiscountEntities ctx = new whatsmydiscountEntities();
int IdRelationshipItems = Convert.ToInt32(Request.QueryString["IdRelationshipItems"]);
int IdProductService = Convert.ToInt32(Request.QueryString["IdProductService"]);
var Items = (from es in ctx.State
join ie in ctx.ItemsStates on es.StateId equals ie.StateId
join i in ctx.Items on ie.IdItem equals i.IdItem
join iir in ctx.ItemsRelationshipItems on i.IdItem equals iir.IdItem
join ir in ctx.RelationshipItems on iir.IdRelationshipItems equals ir.IdRelationshipItems
join ips in ctx.ItemsProductsServices on i.IdItem equals ips.IdItem
join ps in ctx.ProductsServices on ips.IdProductService equals ps.IdProductService
where iir.IdRelationshipItems == IdRelationshipItems
&& ips.IdProductService == IdProductService
&& ir.Active == 1
&& i.Active == 1
select new
{
ItemName = i.Name,
StateSigla = es.Sigla,
ProductServiceName = ps.Ttitle,
RelationshipItemName = ir.Name,
RelationshipItemImage = ir.Image,
RelationshipItemActive = ir.Active,
ItemSite = i.Site,
ItemDescription = i.Description,
ItemAddress = i.Address,
Iteminformationdiscount = i.information_discount,
ItemLogo = i.Logo,
ItemActive = i.Active,
StateId = ie.StateId,
IdRelationshipItems = iir.IdRelationshipItems,
IdProductService = ips.IdProductService
}).ToList();
}
As you can see, the result will be 1 row for each state, if the user passes the IdRelationshipItems and the IdProductService.
Instead of 1 row for each state with the same information, I'd like to show only 1 row and all the states separated by commas. What do I need to change to do this?

I had to solve this problem today. I have a view model that looks like this:
public class IndexViewModel
{
public string Search { get; set; }
public IPagedList<MembershipUser> Users { get; set; }
public IEnumerable<string> Roles { get; set; }
public bool IsRolesEnabled { get; set; }
public IDictionary<string,string> Tags { get; set; }
}
I needed to return a unique list of users and all of the Tags that are assigned to them as a comma separated string.
The data is stored like this:
"41FFEC0F-B920-4839-B0B5-862F8EDE25BD", tag1
"41FFEC0F-B920-4839-B0B5-862F8EDE25BD", tag2
"41FFEC0F-B920-4839-B0B5-862F8EDE25BD", tag3
And I needed output that looked something like this:
"41FFEC0F-B920-4839-B0B5-862F8EDE25BD", "tag1, tag2, tag3"
I ended up creating a List of UserId's like this (I'm using the MembershipProvider which exposes the UserId as ProviderUserKey):
var userIdList = users.Select(usr => (Guid) usr.ProviderUserKey).ToList();
The object "users" is a MembershipUser object. I then call a function in my service passing the List in like this:
Tags = _usersTagsService.FindAllTagsByUser(userIdList)
And my service function looks like this:
public IDictionary<string, string> FindAllTagsByUser(IList<Guid> users)
{
var query = (from ut in _db.UsersTags
join tagList in _db.Tags on ut.TagId equals tagList.Id
where users.Contains(ut.UserId)
select new {ut.UserId, tagList.Label}).ToList();
var result = (from q in query
group q by q.UserId
into g
select new {g.Key, Tags = string.Join(", ", g.Select(tg => tg.Label))});
return result.ToDictionary(x=>x.Key.ToString(),y=>y.Tags);
}
I'm pretty sure these two linq statements can probably be combined into one but I find it easier to read this way. Still only hits the database once.
Things to watch out for:
I was originally passing just IList users into the function FindAllTagsByUser and linq couldn't infer the type and therefore wouldn't let me use the .Contains extension method. Kept saying that linq to entities didn't support Contains.
You need to do a .ToList() on the first query to materialize it or you will get trouble from linq to entity when you try to use string.Join to create the comma separated list.
Good luck
dnash

Related

how to select records from multiple table with max count value from one table using Linq in Asp.net MVC C#

I have 3 tables:
1. Tbl_Model,
2. Tbl_ModelImg,
3. Tbl_Category
I want to know how to fetch the records from these 3 tables using categoryId.
The single model may have multiple images, but I want to show all the products of that category with their images. The problem is I only want a single image in that view. So when a user clicks on that particular model, the details of that model and all its images will show on the next view.
The following query is working fine but it displays all the images with their model name. Means If a model has 4 images than on category details page it displays 4 items with the same name and different images.
Here is the model class :
public class showdata
{
public Tbl_ModelImg tmi { get; set; }
public Tbl_Model tm { get; set; }
public Tbl_SubCategory tblsubcategory { get; set; }
}
public ActionResult Categorydetails(string sid)
{
var sId = Int64.Parse(new
StandardModule().Decrypt(HttpUtility.UrlDecode(sid.ToString())));
try
{
var query = (from c in db.Tbl_Model
join o in db.Tbl_ModelImg
on c.Model_Id equals o.Model_Id
join d in db.Tbl_SubCategory on c.SubCategory_Id
equals d.Id
where c.SubCategory_Id == sId
select new showdata()
{
tm = c,
tmi = o,
tblsubcategory = d
}).OrderByDescending(d => d.tm.Id).ToList();
return View(query);
}
Replace the second line of the LINQ query with
join o in db.Tbl_ModelImg.GroupBy(m => m.Model_Id).Select(m => m.First())
The GroupBy() will group the items in Tbl_ModelImg by Model_Id and then the Select() will cut the contents of the resulting dataset down to just the first item in each group.
Once the where clause restricts your results to just those that items that join to the correct SubCategory_Id then you have what you need.
var query = (from c in db.Tbl_Model
join o in db.Tbl_ModelImg.GroupBy(m => m.Model_Id).Select(m
=> m.FirstOrDefault())
on c.Model_Id equals o.Model_Id
join d in db.Tbl_SubCategory on c.SubCategory_Id equals d.Id
where c.SubCategory_Id == sId
select new showdata()
{
tm = c,
tmi = o,
tblsubcategory = d
}).OrderByDescending(d => d.tm.Id).ToList();

Multiple data query with LINQ

I have a function to get data from my database with join on it. I want to take data from different tables, how can I achieve this? I want to take "libelle_motif" which is from the table "motif_deplacement"
My function right now:
public static List<personne> getPersonne_Deplacement(int numDeplacement)
{
List<personne> desP = new List<personne>();
var query = (from Per in db.personne.ToList()
join Dep in db.deplacement_personne.ToList() on Per.num_personne equals Dep.num_personne
join Mot in db.motif_deplacement.ToList() on Dep.id_motif equals Mot.id_motif
where Dep.id_deplacement == numDeplacement
select new personne
{
nom_personne = Per.nom_personne,
num_personne = Per.num_personne,
ref_personne = Per.ref_personne,
libelle_motif = Mot.libelle_motif,
});
desP = query.ToList();
return desP;
}
And this is how my database looks like :
You will have to create a new class which will act as the model with the properties you want. Construct one of those in your select based on the included relationships.
Also it much easier to manage this query if you model your relationships in your EF entities as opposed to writing out join statements in every query.
Also notice that I removed all the calls to ToList. Your previous code was materializing all entities from each table and then joining and filtering in memory which is extremely inefficient.
public static List<SomeModel> getPersonne_Deplacement(int numDeplacement)
{
var query = from Per in db.personne
join Dep in db.deplacement_personne on Per.num_personne equals Dep.num_personne
join Mot in db.motif_deplacement on Dep.id_motif equals Mot.id_motif
where Dep.id_deplacement == numDeplacement
select new SomeModel
{
nom_personne = Per.nom_personne,
num_personne = Per.num_personne,
ref_personne = Per.ref_personne,
libelle_motif = Mot.libelle_motif,
};
return query.ToList();
}
SomeModel.cs
public class SomeModel
{
public string nom_personne {get;set;}
public string num_personne {get;set;}
public string ref_personne {get;set;}
public string libelle_motif {get;set;}
// add additional properties as needed
}
I don't know if my answer is related to your question. But why don't you use .Include()
Ex:
var result = db.personne.Include(x => x.deplacement_personne).ThenInclude(x => x.motif_deplacement)
It will give you this structure:
obj personne { nom_personne, ... , obj deplacement_personne { ... , obj motif_deplacement }
You can also select any cols with .Select() , or filter it with .Where().

Linq Query Return Duplicate Record From Sql Database

I am trying to join three linq queries into single query and display the records into an angular js application. But the problem is when I enter the account number and click the submit button, it also displays the duplicate record.
Here is the Linq Query:
public string TranscationDetails(string Account_Number)
{
var accountNumber = int.Parse(Account_Number);//It could be better to use TryParse
using (HalifaxDatabaseEntities context = new HalifaxDatabaseEntities())
{
var CombinedQuery = (from x in context.Current_Account_Deposit
join y in context.Current_Account_Withdraw on x.Account_Number equals y.Account_Number
join z in context.Current_Account_Details on y.Account_Number equals z.Account_Number
where x.Account_Number == accountNumber
select new
{
x.Account_Number,
x.Amount,
Amount1 = y.Amount,
z.Account_Balance,
}).ToList();
var js = new System.Web.Script.Serialization.JavaScriptSerializer();
return js.Serialize(CombinedQuery); // return JSON string
}
}
Some people suggest me on this link ..
http://www.advancesharp.com/blog/1108/linq-inner-join-left-outer-join-on-two-lists-in-c-with-example
Here is the database record screenshot:
Here is the screen shot when i clicked the button with account number and Linq query also display the duplicate record.
May be you can use this concept of class
ReturnClass
{
Current_Account_Details detail {get;set;}
List<Current_Account_Withdraw> listofwithdraw {get;set;}
List<Current_Account_Deposit> listofdeposit {get;set;} }
}
Example : (code may not working :D )
I'll use lambda
context.Current_Account_Details.Select(x => new
{
x.Account_Number,
detail = x,
listofwithdraw = x.Current_Account_Withdraw.ToList(),
listofdeposit = x.Current_Account_Deposit.ToList()
}).ToList();

How to join two or more tables in entity framework and display selected columns from each tables in data grid view

I have generated Entity from database using VS. Now when I want to join two tables from my database and show the result using datagrid view.
my LINQ is :
result = (from lang in my_entity.LANGUAGE
join c in my_entity.COUNTRY
on lang.COUNTRY_ID equals c.ID
select lang).ToList<LANGUAGE>();
dgvresult.DataSource = result;
dgvresult.Refresh();
All the columns from Language tables are shown but none are shown from Country table.
I want few columns from language and few columns from country table to be shown in datagrid view.
How do I do it. Any learning links are also appreciated.
Also I want to learn DataGrid View in detail. If any one can suggest good books or materials , please do.
You can create a new anonymous type and then bind to it, like so:
result = (from lang in my_entity.LANGUAGE
join c in my_entity.COUNTRY
on lang.COUNTRY_ID equals c.ID
select new
{
lang.Col1,
land.col2,
c.Col1,
c.Col2
}).ToList();
dgvresult.DataSource = result;
dgvresult.Refresh();
Or you can create a view model and simply select the values into it:
public class LangCountryModel
{
public string LangCol1 { get; set; }
public string LangCol2 { get; set; }
public string CountryCol1 { get; set; }
public string CountryCol2 { get; set; }
}
result = (from lang in my_entity.LANGUAGE
join c in my_entity.COUNTRY
on lang.COUNTRY_ID equals c.ID
select new LangCountryModel
{
LangCol1 = lang.Col1,
LangCol2 = land.col2,
CountryCol1 = c.Col1,
CountryCol2 = c.Col2
}).ToList();
var result = (from ob1 in lista1
join ob2 in lista2
on ob1.Id equals ob2.Id
select new
{
ob1.Age,
ob2.CarName
}).ToList();
dgvresult.DataSource = result;
dgvresult.Refresh();
Like #pingoo answer with a small edit:
You can do it without using the Join LINQ keyword by using the navigation property COUNTRY of the source table LANGUAGE like this:
result = (from lang in my_entity.LANGUAGE
select new {
lang.Col1,
lang.col2,
lang.COUNTRY.COUNTRY_ID
}).ToList();
dgvresult.DataSource = result; dgvresult.Refresh();`
(...).ToList<LANGUAGE>()
.Select(p=>new{p.LanguageProp,p.COUNTRY.COUNTRYProp,...})

Linq - Many to Many. select with dropdown

I got these 3 tables
tblDocument(DocId, DocName)
tblSubPerson(DocId, PersonId)
tblPerson(PersonId, PersonName)
ddlPerson has all my persons relatet to it.
i'm trying to write a linq query where i want to return all the documents ind tblDocument where the selected person has a relation to and display it in a repeter
got this far.... don't know if i'm doing it wrong
public void testing()
{
string se = ddlPerson.SelectedValue;
var data = new MyModelContext();
rptResult.DataSource = from y in data.tblDocuments
join p in data.tblSubPersons on y.DocId equals p.DocId
select p.PersonId.Equals(se);
rptResult.DataBind();
}
Your query returns collection of bool values, because that's what Equals() method returns. You should use where clause to get only documents for given person:
var personId = int.Parse(ddlPerson.SelectedValue);
var data = new MyModelContext();
var documents = from d in data.tblDocumenta
join sp in data.tblSubPerson on d.DocId equals sp.DocId
where sp.PersonId == personId
select d;
rptResult.DataSource = documents.ToList();
rptResult.DataBind();

Categories

Resources