Linq retrieve non repeated values - asp.net

I have two tables Event_Day and Event_Session which is like this
Event_Day
Event_Day_Id(PK) Event_Id DayNo Day_Date
420 120 1 20/6/2013
421 120 2 21/6/2013
422 120 3 22/6/2013
Event_Session
Event_Session_Id(PK) Event_Id Event_Day_Id
170 120 420
171 120 420
172 120 420
173 120 421
174 120 421
175 120 421
I Want to retrieve by comparing data from these two table using Linq
Event_Day_Id DayNo DayDate
420 1 21/6/2013
421 2 22/6/2013
Pls help me to retrieve data using Linq

You want to use the Enumerable.Distinct LINQ method. Read the documentation here. You first want to do a join on the two tables (suppose your data sets are eventSessions and eventDays):
var dayInfo = from sess in eventSessions
join day in eventDays
on sess.Event_Day_Id equals day.Event_Day_Id
select new { Event_Day_Id = sess.Event_Day_Id, DayNo = day.DayNo, DayDate = sess.Day_Date };
If you are unfamiliar with LINQ equijoins, read the documentation here.
After that, you want to use the Distinct method:
var uniqueDayInfo = dayInfo.Distinct();
Note that Distinct also has an overload that takes in an IEqualityComparer, in cases where you do not want to use default equality comparison. The initial LINQ query (the one that initializes the dayInfo variable) ends with a projection to an anonymous type. The default equality comparison for anonymous types runs default equality comparison on all the properties. Read more about anonymous types and the overridden Equals method here.
If all the selected properties are simple (ints, DateTimes, etc.), this should be sufficient for the Distinct to work as desired without providing the optional IEqualityComparer argument.

If you have a helper class to create a comparer (shown below) you can do it like this:
var unique_session = Sessions.Distinct(
new GenComp<Event_Session>((a,b) =>
(a.Event_Id == b.Event_Id) && (a.Event_Day_Id == b.Event_Day_Id),
(a) => a.Event_Id.GetHashCode()+a.Event_Day_Id.GetHashCode()));
var result = unique_session.Join(Days,
s => new { Event_Id = s.Event_Id, Event_Day_Id = s.Event_Day_Id },
d => new { Event_Id = d.Event_Id, Event_Day_Id = d.Event_Day_Id },
(s, d) => new { Event_Day_Id = d.Event_Day_Id,
DayNo = d.DayNo,
DayDate = d.Day_Date });
Here is the helper class
public class GenComp<T> : IEqualityComparer<T>
{
public Func<T, T, bool> comp { get; private set; }
public Func<T, int> hash { get; private set; }
public GenComp(Func<T, T, bool> inComp, Func<T,int> inHash)
{
comp = inComp;
hash = inHash;
}
public GenComp(Func<T, T, bool> inComp)
{
comp = inComp;
hash = null;
}
public bool Equals(T x, T y)
{
return comp(x, y);
}
public int GetHashCode(T obj)
{
return hash == null ? obj.GetHashCode() : hash(obj);
}
}
Full source code test which runs under LinqPad is here: https://gist.github.com/hoganlong/5820080
Which returns the following:
Note: I suggest LinqPad at LinqPad.com for solving these types of problems - it rocks.

Related

C# how to return multiple query in foreach

Because currently im like unable to retrieve the issue that
public IQueryable<Issue> commodityMatch_GetData(){
string userName = HttpContext.Current.User.Identity.Name;
Context db = new Context();
IQueryable<Issue> query = db.Issues;
//currently is filter by commodity and product line
//looking on how to only filter by commodity
var x = from r in db.Records
where r.Username1 == userName
select r.CommodityID;
System.Diagnostics.Debug.WriteLine("Im fucking here");
foreach(int s in x)
{
//s got 17 and 18
System.Diagnostics.Debug.WriteLine(s);
query = query.Where(p => p.CommodityID == s);
//how to run mutiple time and return multiple times?
//return mean end
}
return query;
}
For example in var x i have 2 int which is 17 and 18 but in above code i unable to retrieve the issue where the commodity = 17 and 18.
foreach(int s in x)
{
//s got 17 and 18
System.Diagnostics.Debug.WriteLine(s);
query = query.Where(p => p.CommodityID == s);
return query;
}
if return query here it only show me issue with commodity 17 and then it didnt show for issue with commodity 18.
Trying joining the issues to the records for a single LINQ query:
var x = from r in db.Records
join i in db.Issues
on r.CommodityID == iCommodityID
where r.Username1 == userName
select i;
return x;

is there a way to get rid of DTO

I am using Entity Framework. I have the following query in which I get data using two tables Application and Employee connected by a foreign key EmployeeID in Application Table. The tables have 1-1 relationship .
Is there a way to simplify the following code and get rid of the DTO Employee1
which is the same as auto generated Employee class
public List<Employee1> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = (from a in context.Applications
join e in context.Employees on a.EmployeeID equals e.EmployeeID
where
(
a.ApplicationID == ApplicationID
)
select new Employee1
{
EmployeeID = e.EmployeeID,
SecondEmail = e.SecondEmail,
EmailID = e.EmailID,
Title = e.Title,
Name = e.Name,
Rank = e.Rank,
POBox = e.POBox,
Phone = e.Phone,
JoinDate = e.JoinDate,
Status = e.Status,
DepartmentID = e.DepartmentID.Value,
NameString = e.NameString,
Department = e.Department,
ParentDept = e.ParentDept,
DepartmentAr = e.DepartmentAr,
NameAr = e.NameAr,
NameStringAr = e.NameStringAr,
TitleAr = e.TitleAr
}).ToList();
return data;
}
If you need to return list of Employees, just select e which refers to Employee and don't use Employee1 as a DTO.
public List<Employee> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = (from a in context.Applications
join e in context.Employees on a.EmployeeID equals e.EmployeeID
where
(
a.ApplicationID == ApplicationID
)
select e).ToList();
return data;
}
Another way is this, which I would prefer because of readability:
public List<Employee> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = context.Applications.Where(p=>p.ApplicationID == ApplicationID).Select(p=>p.Employee).ToList();
return data;
}

Get minimum value from list

I have a class ABC like this
public class ABC{
public int Id {get;set;}
public int UserCount {get;set;}
}
Now I add following records to a list of type ABC
List<ABC> lstABC = new List<ABC>();
lstABC.Add(new ABC(){Id=1,UserCount=5});
lstABC.Add(new ABC(){Id=2,UserCount=15});
lstABC.Add(new ABC(){Id=3,UserCount=3});
lstABC.Add(new ABC(){Id=4,UserCount=20});
I've another list of type int
List<int> lstIds = new List<int>();
lstIds.Add(1);
lstIds.Add(3);
lstIds.Add(4);
Now i want to find out the minimum value of UserCount by comparing both the list where Id in lstABC should match the items presesnt in lstIds. I can get the minimum value of UserCount by using loops but is there any another way to get the value in an optimized way by avoiding loops?
You can use Enumerable.Join to link both lists:
var joined = from id in lstIds
join x in lstABC
on id equals x.Id
select x;
int minValue = joined.Min(x => x.UserCount);
This is more efficient than loops since Join uses a set to find matching items.
There's more than one way to skin a cat, this is a little bit less efficient:
int minValue = lstABC.Where(x => lstIds.Contains(x.ID)).Min(x => x.UserCount);
Try below code:
int min = lstABC.Min(entry => entry.UserCount);
var a = lstABC.Where(e => e.UserCount == min).FirstOrDefault();
var resul = lstIds.Where(e => e.Equals(a.Id)).FirstOrDefault();
var result = lstABC.Where(n =>n.Id == resul).FirstOrDefault();

StoreRequestParameters,get the values issue

on the web service side I am applying
StoreRequestParameters parameters = new StoreRequestParameters(this.Context);
string condition= parameters.GridFilters.ToString();
//I ma sending this to the methot "List<Ks> Get(....)"
to get the gridfilter parameters.
inside the other methot ,trying to get the selected gridfilters values like this.
public List<Ks> Get(int start, int limit, string sort, string terssiralama, string condition, out int totalrow)
{
FilterConditions fc = new FilterConditions(condition);
foreach (FilterCondition cnd in fc.Conditions)
{
Comparison comparison = cnd.Comparison;
string fi = cnd.Field;
FilterType type = cnd.Type;
switch (cnd.Type)
{
case FilterType.Date:
switch (comparison)
{
case Comparison.Eq:
field1 = cnd.Field;
cmp1 = "=";
value1 = cnd.Value<string>();
...........
..........
}
but I failed getting the values like this
FilterConditions fc = new FilterConditions(condition);
I couldnt pass the string values .
should I serializes or deserilized first ?
StoreRequestParameters parameters = new StoreRequestParameters(this.Context);
instead of using this, string condition= parameters.GridFilters.ToString();
I use this
string obj = this.Context.Request["filter"];
and pass it to the
FilterConditions fc = new FilterConditions(obj);
It can be reach all filter condition in fc filtercondition variable.

linq sum and group [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dynamic Anonymous type in Razor causes RuntimeBinderException
I have this Linq Agregate Query
var GruposQ = from lcGrupos in db.Merlin_ConceptosFacturacion_Kit_Componentes
where lcGrupos.NumIdConcepto == Item.NumIdConcepto & lcGrupos.BitComponenteVariable == true
select lcGrupos;
var GruposList = from comps in GruposQ
group comps by
new
{
NumIdGrupoProducto = comps.NumIdGrupoProducto,
} into g
select new
{
NumIdTransaccion = NumIdTransaccion,
NumIdGrupoProducto = g.Key.NumIdGrupoProducto,
NumCantidad = g.Sum(x=>x.NumCantidad),
Grupo = GruposQ.Where(x => x.NumIdGrupoProducto == g.Key.NumIdGrupoProducto)
};
ViewBag.CompsKit = GruposList.ToList();
My problem is when I try to get elements from ViewBag.CompsKit:
#foreach (var myTrans in ViewBag.CompsKit)
{
// Here it throws an error
// 'object' does not contain a definition for 'NumIdtransaccion'
<span>myTrans.NumIdtransaccion</span>
}
But if i look into this object it allready has the property.
myTrans { NumIdTransaccion = 15460
, NumIdGrupoProducto = 163
, NumCantidad = 100,000
, Grupo = System.Data.Common.Internal.Materialization.CompensatingCollection`1[ParadigmaNet.Areas.Items.Models.Merlin_ConceptosFacturacion_Kit_Componentes] } dynamic {<>f__AnonymousType7<decimal,decimal?,decimal,System.Linq.IQueryable<ParadigmaNet.Areas.Items.Models.Merlin_ConceptosFacturacion_Kit_Componentes>>}
How can I do to access the properties ? in this agregate ?
You can't use "dynamic" type in a Razor View.
You must use a typed object as Model.
You can do grouping and filtering in single query:
var numIdConcepto = Item.NumIdConcepto;
var query = from comps in db.Merlin_ConceptosFacturacion_Kit_Componentes
where comps.NumIdConcepto == numIdConcepto &&
comps.BitComponenteVariable
group comps by comps.NumIdGrupoProducto into g
select new
{
NumIdGrupoProducto = g.Key,
NumCantidad = g.Sum(x => x.NumCantidad),
Grupo = g.ToList()
};
ViewBag.CompsKit = query.ToList();
ViewBag.NumIdTransaccion = NumIdTransaccion;
Also
you don't need create anonymous object for grouping by single property
you don't need to compare boolean values with true/false
you can simply use g.Key when use single property for grouping
items in group already will have NumIdGrupoProducto equal to grouping key
Instead of assigning same NumIdTransaccion to each group in the query result, pass that value to view separately: ViewBag.NumIdTransaccion = NumIdTransaccion
View:
<span>ViewBag.NumIdTransaccion</span>
#foreach(var item in ViewBag.CompsKit)
{
<span>#item.NumIdGrupoProducto</span>
<span>#item.NumCantidad</span>
}
Consider also creating ViewModel for this view - thus you will be safe about typos and all such errors will be eliminated at compile time.

Resources