group by base on 2 element - linq

equal this
select id,name, count(*) from table group by id, name
what is in linq???

In case of entity framework it is better to return computed projection directly from SQL:
var query = from x in context.YourEntities
group x by new { x.ID, x.Name } into y
select new
{
y.Key.ID,
y.Key.Name,
y.Count()
};
This will do Count in database and reduce amount of transferred data.

var groups = table.GroupBy(elt => new {ID = elt.ID, Name = elt.name});
foreach (var group in groups)
{
var ID = group.Key.ID;
var name = group.Key.Name;
var count = group.Count();
...
}

Related

IQueryable.Union/Concat in .net core 3

I want to add a dummy member to an IQueryable and came up with this solution:
IQueryable<Geography> geographies = _unitOfWork.GeographyRepository.GetAll(); //DbSet<Geography>
var dummyGeographies = new Geography[] { new Geography { Id = -1, Name = "All" } }.AsQueryable();
var combinedGeographies = geographies.Union(dummyGeographies);
var test = combinedGeographies.ToList(); //throws runtime exc
But it throws the following exception:
Processing of the LINQ expression 'DbSet
.Union(EnumerableQuery { Geography, })' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core.
How could I make it work?!
you can only union on data structure which are the same
IQueryable is only applicable if the query expression not been been expressed (ToList) before its run against db and you want the expression modifiable . aka nothing which which is not going to db as a query needs to be IQueryable (simple explanation better to research and understand this yourself)
List<Geography> geographies = _unitOfWork.GeographyRepository
.GetAll() //DbSet<Geography>
.Select(o => new Geography { Id = o.Id, Name = o.Name })
.ToList();
List<Geography> dummyGeographies = new List<Geography>() {
new Geography[] { new Geography { Id = -1, Name = "All" } }
};
var combinedGeographies = geographies.Union(dummyGeographies);
var test = combinedGeographies.ToList();
I was able to achieve it with the following code:
IQueryable<Geography> geographies = _unitOfWork.GeographyRepository.GetAll().Select(o => new Geography { Id = o.Id, Name = o.Name });
IQueryable<Geography> dummyGeographies = _unitOfWork.GeographyRepository.GetAll().Select(o => new Geography { Id = -1, Name = "All" });
var combinedGeographies = geographies.Union(dummyGeographies);

Converting dynamic row into column in linq

var Getitems = (from u in db.EmailSettings
join s in db.SecurityRoles on u.SecurityRoleID equals s.SecurityRoleID
group u by new { u.SecurityRoleID,s.SecurityRoleName} into g
select new
{
TransTypeId = (from v in db.EmailSettings
//join s in db.SecurityRoles on v.SecurityRoleID equals s.SecurityRoleID
where v.SecurityRoleID == g.Key.SecurityRoleID
select new
{
//username = s.SecurityRoleName,
trans = v.TransTypeID
}),
SecurityRoleName=g.Key.SecurityRoleName,
SecurityRoleId=g.Key.SecurityRoleID,
}).ToList();
For example in TransTypeId i have 3 rows of data .. i want to convert tat to single row like SecurityRoleName ,SecurityRoleId,Row1,row2,row3..
where TransTypeId can have any no of rows .. do any one help me to get the desired result
i want the result as the above screen
var Getitems = (from u in db.EmailSettings
join s in db.SecurityRoles on u.SecurityRoleID equals s.SecurityRoleID
group u by new { u.SecurityRoleID,s.SecurityRoleName} into g
select new
{
TransTypeId = (from v in db.EmailSettings
//join s in db.SecurityRoles on v.SecurityRoleID equals s.SecurityRoleID
where v.SecurityRoleID == g.Key.SecurityRoleID
select new
{
//username = s.SecurityRoleName,
trans = v.TransTypeID
}),
SecurityRoleName=g.Key.SecurityRoleName,
SecurityRoleId=g.Key.SecurityRoleID,
}).ToList();
After that you can get the above result by creating a new list in every for each loop by using transactiontypenames = new List() like below code
List<transactiontypename> transactiontypenames;
transactiontypename transactiontypenameobj;
foreach (var x in Getitems)
{
transactiontypenames = new List<transactiontypename>();
objsecurityVM = new SecurityRoleVM();
objsecurityVM.User = x.SecurityRoleName;
objsecurityVM.SecurityRoleId = x.SecurityRoleId;
foreach (var y in x.TransTypeId)
{
transactiontypenameobj = new transactiontypename();
transactiontypenameobj.Transtypes = y.trans;
transactiontypenames.Add(transactiontypenameobj);
}
objsecurityVM.TransTypes = transactiontypenames;
objlistsecurityroleVM.Add(objsecurityVM);
}
objEmailSetting.TableData = objlistsecurityroleVM;
return View(objEmailSetting);
Hope it will be useful for you

Dynamic LINQ Where query with joining other tables

I have several tables (the exact number is not known when the program is build) looking like this (the number of rows and columns may differ from table to table):
The source data is stored in a data set. Now I want to generate a new table where all data of all ids is stored (the picture shows only the result for id 10 and 20 but the target table should contain the data for all ids):
The equivalent SQLite statement for that looks like this:
SELECT * FROM Dataset
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=10
UNION
SELECT * FROM Dataset
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=20
...
The double id columns will be removed afterwards so donĀ“t worry about that. The questions is now how to convert it as a dynamic LINQ query?
There are plenty of open question but maybe this helps to solve it. Since the tables are already stored in a DataSet you could use Linq-To-DataSet and Enumerable.GroupBy to group by ID:
var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("Id"));
if(!idTables.Any()){ MessageBox.Show("No id-tables"); return; }
var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
.GroupBy(row => row.Field<int>("Id"))
.Select(grp => new { ID = grp.Key, Rows = grp });
foreach(var idGroup in idRowGroups)
{
Console.WriteLine("ID:{0} Rows:{1}"
, idGroup.ID
, String.Join(" | ", idGroup.Rows.Select(row => String.Join(",", row.ItemArray))));
}
Sample data:
var ds = new DataSet();
DataTable t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(1, 1);
t1.Rows.Add(2, 10);
t1.Rows.Add(3, 100);
t1.Rows.Add(4, 1000);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(4, 5);
t1.Rows.Add(5, 50);
t1.Rows.Add(7, 500);
t1.Rows.Add(3, 5997);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data1", typeof(int));
t1.Columns.Add("Data2", typeof(int));
t1.Rows.Add(1, 5, 0);
t1.Rows.Add(3, 7, 1);
t1.Rows.Add(5, 9, 11);
t1.Rows.Add(7, 11, 222);
ds.Tables.Add(t1);
Output:
ID:1 Rows:1,1 | 1,5,0
ID:2 Rows:2,10
ID:3 Rows:3,100 | 3,5997 | 3,7,1
ID:4 Rows:4,1000 | 4,5
ID:5 Rows:5,50 | 5,9,11
ID:7 Rows:7,500 | 7,11,222
Ok, I finally made it but it seems to be much too complicated. If someone is able to help me improve the solution he is very welcome.
DataSet dsResult = new DataSet();
var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("ID"));
if (!idTables.Any()) { MessageBox.Show("No id-tables"); return; }
var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
.GroupBy(row => row.Field<Int64>("ID"))
.Select(grp => new { ID = grp.Key, Rows = grp });
foreach (var idGroup in idRowGroups)
{
var liste = idGroup.Rows.ToList();
for (int i = 0; i < liste.Count; i++)
{
if (!dsResult.Tables.Contains(liste[i].Table.TableName))
{
dsResult.Tables.Add(liste[i].Table.TableName);
foreach (DataColumn dtCol in liste[i].Table.Columns)
{
if (dsResult.Tables[liste[i].Table.TableName].Columns.Contains("ID"))
dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName+i.ToString());
else
{
dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName);
}
dsResult.Tables[liste[i].Table.TableName].Columns[dtCol.ColumnName].DataType = dtCol.DataType;
}
}
DataRow dRow = dsResult.Tables[liste[i].Table.TableName].NewRow();
dRow.ItemArray = liste[i].ItemArray;
dsResult.Tables[liste[i].Table.TableName].Rows.Add(dRow);
}
IEnumerable<IEnumerable<DataRow>> allTablesRows = dsResult.Tables.Cast<DataTable>()
.Select(table => table.AsEnumerable())
.CartesianProduct();
int k = 0;
foreach (var rows in allTablesRows)
{
DataRow zRow = dsErgebnis.Tables[2].NewRow();
foreach (DataRow dRow in rows)
{
for (int i = 0; i < dRow.ItemArray.Length; i++)
{
zRow[k] = dRow.ItemArray[i];
k++;
}
}
k = 0;
dsErgebnis.Tables[2].Rows.Add(zRow);
}
dsResult.Clear();
}
First I filter the content by ID.
Then I put the result in a new tables (all rows with the ID 10 I found in 'Datasatz2' in dataset 'ds' for example I put to a new table 'Datasatz2' in the dataset 'dsResult').
At least I build the cartesian product of all tables and store it in dtaset dsErgebnis.
The result is what I expect but as mentioned before I am not satisfied with the solution.

Filtering data from 2 table

Here I have 2 query variable for showing a different type of data,But i want to extract a particular data from first query ,which don't have reference in second query
I have the following code,but it does not work properly as.first query variable is used to join 4 table like A,B,C,D and Second Query variable Join table A and B.Here i want a data from First variable and it don't have any reference in second table
public List<ProductEntityList> GetProductListRegister()
{
var ProductList1 = new List<ProductEntityList>();
var ProductList = new List<ProductEntityList>();
var finalList = new List<ProductEntityList>();
try
{
using (HabitGreen01Entities ob = new HabitGreen01Entities())
{
var list1 = from ctr in ob.TblCreateUsers
join shp in ob.TblShopMasters
on ctr.id equals shp.Fk_CreateUser_Id
join prd in ob.TblProductMaster01
on shp.id equals prd.FK_ShopMaster_Id
select new ProductEntityList
{
Id = prd.id,
Name = prd.Name,
ShopName = shp.Name,
UserName = ctr.Name
};
ProductList1 = list1.ToList();
var temp = from pd in ob.TblProductMaster01
join cr in ob.TblAccountSettings
on pd.id equals cr.f_productmaster01Id
select new ProductEntityList
{
Id = (int)cr.f_productmaster01Id,
Name=pd.Name
};
ProductList = temp.ToList();
var temp1 = from item in ProductList1
where !ProductList.Contains(x=>item.Id)
select new ProductEntityList
{
Id = item.Id,
Name = item.Name,
ShopName = item.ShopName,
UserName = item.UserName
};
finalList = temp1.ToList();
// var temp1= ProductList1.Select(f=>f.Id).Intersect(ProductList.Select(b=>b.Id));
//finalList = matches.ToList();
}
}
catch (Exception e)
{
throw e;
}
return (finalList);
}
Try this:
var temp1 = from item in ProductList1
where !ProductList.Select(c=>c.Id).Contains(item.Id)
select new ProductEntityList
{
Id = item.Id,
Name = item.Name,
ShopName = item.ShopName,
UserName = item.UserName
};
You can write directly:
var finalList = (from item in ProductList1
where !ProductList.Select(c=>c.Id).Contains(item.Id)
select new ProductEntityList
{
Id = item.Id,
Name = item.Name,
ShopName = item.ShopName,
UserName = item.UserName
}).ToList();
var result = ProductList1.Where(p => !ProductList.Any(p2 => p2.Id== p.Id));
finalList = result.ToList();

DataTable linq query iteration

I want to Enumerate Linq Query. Below i specified example.
EX:
DataTable _slidingDataTable = new DataTable("test");
for(int i=0; i<5;i++)
{
DataRow row = _slidingDataTable.NewRow();
startPosition = DateTime.Now;
for(int i=0; i<5;i++)
{
_slidingDataTable.Columns.Add("TransferTime");
row[columnName] = startPosition ;
_slidingDataTable.Columns.Add("TransferData");
row[columnName] = "Test"+i;
}
_slidingDataTable.Rows.Add(row);
}
var query1 = from myRow in _slidingDataTable.AsEnumerable()
where myRow.Field<DateTime>("TransferTime") == startPosition
select myRow;
This query output should be collection of rows. How to get collection row & iterate.
In your context, query1 is an EnumerableRowCollection<DataRow> because you used _slidingDataTable.AsEnumerable(), and you can iterate over it like so :
foreach (DataRow row in query1)
{
// Do stuff with that row
}
I'm giving you an example by which you can see it and it also includes sum in groupby.
var drdatedisp = from row in dtfullreport.AsEnumerable()
group row by row.Field<string>("Order_Date") into g
select new
{
Order_Date = g.Key,
totalQnty = g.Sum(a => a.Field<int>("Item_Quantity")),
totalTax = g.Sum(a => float.Parse(a.Field<decimal>("TAXAMT").ToString())),
totalAmt = g.Sum(a => float.Parse(a.Field<decimal>("VALAMT").ToString()))
};
DataTable dtdatedisp = new DataTable();
dtdatedisp.Columns.Add("Order_Date");
dtdatedisp.Columns.Add("Item_Quantity");
dtdatedisp.Columns.Add("TAXAMT");
dtdatedisp.Columns.Add("VALAMT");
dtdatedisp.Rows.Clear();
foreach (var g in drdatedisp)
{
DataRow newRow1 = dtdatedisp.NewRow();
newRow1[0] = g.Order_Date;
newRow1[1] = g.totalQnty;
newRow1[2] = String.Format("{0:0.00}", g.totalTax);
newRow1[3] = String.Format("{0:0.00}", g.totalAmt);
dtdatedisp.Rows.Add(newRow1);
}

Resources