Linq grouping and seting datatables - linq

enter image description hereI have this code for grouping and suming column:
var groupedData = from b in showit.AsEnumerable()
group b by b.Field<string>("Key") into g
select new
{
KeyName = g.Key,
Calls_Chats_Answered = g.Sum(x => x.Field<int>("Calls_Chats_Answered"))
};
How do I pass the groupedData to datatable ?

//Create DataTable
DataTable dt = new DataTable();
//Add DataColumns to DataTable
dt.Columns.Add("KeyName", typeof(string));
dt.Columns.Add("Calls_Chats_Answered", typeof(int));
//Iterate over the query
foreach (var v in groupedData)
{
//Create new DataRow
DataRow dr = dt.NewRow();
//Add values to DataRow
dr["KeyName"] = v.KeyName;
dr["Calls_Chats_Answered"] = v.Calls_Chats_Answered;
//Add DataRow to DataTable
dt.Rows.Add(dr);
}

Related

Contat 2 Lists from different tables into 1 and use AsQueryable()

Attempting to return the below 2 lists into something I can then query against.
var people = (from c in _context.FollowingPeople
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId,
Person = (from p in _context.SocialMediaPeople
where p.Id == c.SocialMediaId
select new Models.SocialMediaPeople
{
Id = p.Id,
Photo = p.Photo
}).FirstOrDefault()
});
var generic = (from c in _context.FollowingGeneric
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId,
Person = null
});
var temp = people.Concat(generic).ToList();
//var data = temp.AsQueryable();
if (!string.IsNullOrEmpty(filter))
{
data = data.Where(filter);
}
data = data.Where(x => x.ClientId == ClientId);
return await data
.GetPaged(page, pageSize);
I have tried join, concat, even Zip but it results in various errors such as
(Unable to translate set operation after client projection has been applied. Consider moving the set operation before the last 'Select' call.)
So I finally got this working, the trick is to not perform any queries on the data until AFTER the concat. Th below works...
var queryA =
from c in _context.Set<FollowingPeople>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var queryB =
from c in _context.Set<FollowingGeneric>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var queryC =
from c in _context.Set<FollowingPublication>()
select new Models.Following.FollowingModel
{
Id = c.Id,
MediaTypeId = c.MediaTypeId,
Title = c.Title,
ClientId = c.ClientId
};
var data = (from v in queryA.Union(queryB).Union(queryC)
select new Models.Following.FollowingModel
{
Id = v.Id,
MediaTypeId = v.MediaTypeId,
Title = v.Title,
ClientId = v.ClientId,
})
.AsNoTracking()
.AsQueryable();
data = data.Where(x => x.ClientId == ClientId);
return await data.GetPaged(page, pageSize);

Linq Implementation With Dynamic GroupBy Clause

In the bellow Linq Statement, i am facing an error in "Select" while trying to fetch, datatable field like "ID" and assign it to row["ID"].
//row["ID"] = g.Field<decimal>("ID");
Error Message:
System.Linq.IGrouping<string,System.Data.DataRow> does not contain a definition for 'Field'
var x = groupedDataRow
.AsEnumerable()
.Select(g =>
{
var row = dataTable.NewRow();
//row["ID"] = g.Field<decimal>("ID");
row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
return row;
}).CopyToDataTable();
How retrieve datatable field like "ID" so that it could be assigned to row["ID"] in the Select statement?
Linq Example
public class Program
{
static StringBuilder stringBuilder = new StringBuilder();
public static String GroupData(DataRow dataRow)
{
String[] columnNames = new[] {"ID","COL1", "COL2"};
stringBuilder.Remove(0, stringBuilder.Length);
foreach (String column in columnNames)
{
stringBuilder.Append(dataRow[column].ToString());
}
return stringBuilder.ToString();
}
public static void Main()
{
DataTable dataTable = new DataTable("MyTable");
DataColumn dc2 = dataTable.Columns.Add("ID", typeof(decimal));
dataTable.Columns.Add("AMT", typeof(decimal));
dataTable.Columns.Add("PERCENTAGE", typeof(decimal));
dataTable.Columns.Add("COL1", typeof(String));
dataTable.Columns.Add("COL2", typeof(String));
dataTable.Rows.Add(000, 400,100,"sss","vvv");
dataTable.Rows.Add(888, 400, 100,"qqq","fff");
dataTable.Rows.Add(000, 300, 100,"eee","aaa");
dataTable.Rows.Add(000, 300, 100,"eee","aaa");
dataTable.Rows.Add(000,400,100,"sss","vvv");
EnumerableDataRowList<DataRow> enumerableRowCollection = new EnumerableDataRowList<DataRow>(dataTable.Rows);
Func<DataRow, String> groupingFunction = GroupData;
var groupedDataRow = enumerableRowCollection.GroupBy(groupingFunction);
var x = groupedDataRow.AsEnumerable()
.Select(g =>
{
var row = dataTable.NewRow();
//row["ID"] = g.Field<decimal>("ID");
row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
return row;
}).CopyToDataTable();
foreach(DataRow row in x.Rows)
{
Console.WriteLine(row["ID"].ToString() + " " + row["COL1"].ToString() + " " + row["COL2"].ToString() + " " + row["AMT"].ToString() + " " + row["PERCENTAGE"].ToString()) ;
}
}
class EnumerableDataRowList<T> : IEnumerable<T>, IEnumerable
{
IEnumerable dataRows;
internal EnumerableDataRowList(IEnumerable items)
{
dataRows = items;
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
foreach (T dataRow in dataRows)
yield return dataRow;
}
IEnumerator IEnumerable.GetEnumerator()
{
IEnumerable<T> iEnumerable = this;
return iEnumerable.GetEnumerator();
}
}
It's because g is an IGrouping which doesn't have a Field member.
You could maybe try something like:
var x = groupedDataRow.AsEnumerable()
.Select(g =>
{
var row = dataTable.NewRow();
row["ID"] = g.Select(r => r.Field<decimal>("ID")).FirstOrDefault();
row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
return row;
}).CopyToDataTable();
or
var x = groupedDataRow.AsEnumerable()
.Select(g =>
{
var row = dataTable.NewRow();
row["ID"] = g.First().Field<decimal>("ID");
row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
return row;
}).CopyToDataTable();
It should be safe to use g.First() because a group is only a group if it contains any items.

How to control null LookUp or Compare different types of List

I have something like this which is getting string categories (from dropdown).
I am taking all list in catList and comparing that item in string[]categories and if it is null add this to newCategories for add to database. And lastly i want to return List<Category> with categories values.
public List<Category> ExistingCategories(string[] categories)
{
var catList = GetAllCategories().ToList();
List<Category> newCategories = new List<Category>();
var existedCategory = catList.ToLookup(x=>x.Name , v=>v.Name);
foreach (var item in categories)
{
var lookUpExistedCategory = existedCategory[item];
if (lookUpExistedCategory != )
{
newCategories.Add(new Category { Name = item });
}
}
CreateCategories(newList);
return GetAllCategories().ToList();
}
How should I do that?
You can use .Contains(TKey value)
So you can replace your foreach loop by
var newCategories = categories
.Where(m => !existedCategory.Contains(m))
.Select(m => new Category{Name = m}).toList()
By the way, I don't see the need of a LookUp<TKey, TValue>, you could use a HashSet<T>
var existedCategory = new HashSet(GetAllCategories().Select(x => x.Name).ToList());
So your method would be
public List<Category> ExistingCategories(string[] categories)
{
var existingCategories = new HashSet(GetAllCategories().Select(x => x.Name).ToList());
var newCategories = categories
.Where(m => !existingCategories .Contains(m))
.Select(m => new Category{Name = m}).toList());
//assuming this method will add and save to your db
CreateCategories(newCategories);
return GetAllCategories().ToList();
}

Bind Telerik DDL

I am trying to bind a Telerik DropDownList.
View Code:
<div>#( Html.Telerik().DropDownList()
.Name("ddlCounty")
.HtmlAttributes(new { style = "width:200px;" })
.SelectedIndex(0)
.BindTo(new SelectList((IEnumerable<MvcNew.Models.tbl_Country>)ViewData["ListCountries"], "Value", "Text")) )
</div>
Controller Code:
List<SelectListItem> lst_Country = new List<SelectListItem>();
var Countries = (from m in DBContext.tbl_Countries
select new SelectListItem{ Text = m.Country__Name.ToString(), Value = m.Country_ID.ToString() });
ViewBag.ListCountries = new SelectList(Countries);
return View();
I am getting the below error
Unable to cast object of type 'System.Web.Mvc.SelectList' to type 'System.Collections.Generic.IEnumerable`1[MvcNew.Models.tbl_Country]'.
I have changed a code like this and it's worked
var clientIDs = DBContext.tbl_Countries
List<SelectListItem> items = new List<SelectListItem>();
foreach (var t in clientIDs)
{
SelectListItem s = new SelectListItem();
s.Text = t.Country__Name.ToString();
s.Value = t.Country__Name.ToString();
items.Add(s);
}
ViewBag.ListCountries = items;

Getting the 1st value in a subset of data

I have a result coming back from a LINQ statement that looks like this:
Id dataId dataVal
A 1 1000
A 2 2000
A 3 3000
A 3 3001
A 3 3002
What I'd like is to just get the 1st item (dataId = 3 and dataVal = 3000)
Here is my query that is generating the above result:
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.Select(x=> new
{
Id = x.Id,
DataId = x.dataId,
DataValue = x.DataValue
}).ToList().Distinct();
Do I need to do some grouping or is there an easier way?
Group your items by dataId, and then select first item from each group:
var myIds = (from a in myList
where ListIds.Contains(a.dataId)
group a by a.dataId into g
let firstA = g.OrderBy(x => x.DataValue).First()
select new {
Id = firstA.Id,
DataId = g.Key,
DataValue = firstA.DataValue
}).ToList();
Or with extension methods (it returns first item in original order):
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.GroupBy(a => a.dataId)
.Select(g => new
{
Id = g.First().Id,
DataId = g.Key,
DataValue = g.First().DataValue
}).ToList();
Use .FirstOrDefault() after the Select
var myIds = myList
.Where(a => ListIds.Contains(a.dataId))
.Select(x=> new
{
Id = x.Id,
DataId = x.dataId,
DataValue = x.DataValue
}).FirstOrDefault();

Resources