Filtering data from 2 table - linq

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();

Related

Append to a Func in LINQ

I have a method with a projection
public IQueryable<EmpDTO> GetEmployee(Func<Employee, EmpDTO> projection = null)
{
if(projection == null)
projection = emp => new EmpDTO {
Id = emp.Id,
Name = emp.Name,
Salary = emp.Salary,
};
return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}
It can be extended as follows:
query = classInstance.GetEmployee(emp => new EmpDTO {
Id = emp.Id,
Name = emp.Name,
Salary = emp.Salary,
Address = emp.Address
});
How can I APPEND only the "Address" field to the Func without
rewriting the entire fields (repeated fields Id, Name, Salary)
Using Expression, you can build a new lambda to initialize the fields:
public IQueryable<EmpDTO> GetEmployee(Expression<Func<Employee, EmpDTO>> addProj = null) {
Expression<Func<Employee, EmpDTO>> projection = emp => new EmpDTO {
Id = emp.Id,
Name = emp.Name,
Salary = emp.Salary,
};
if (addProj != null) {
var pBody = ((MemberInitExpression)projection.Body);
var newBindings = new ReadOnlyCollection<MemberBinding>(pBody.Bindings.Concat(((MemberInitExpression)addProj.Body).Bindings).ToList());
var newBody = Expression.MemberInit(pBody.NewExpression, newBindings);
projection = (Expression<Func<Employee, EmpDTO>>) Expression.Lambda(newBody, projection.Parameters);
}
return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}
You could also build the entire lambda from scratch, but that seemed like more work to me. Plus you can encapsulate the combine init logic into an extension method:
public static Expression<Func<TIn, TOut>> Add<TIn, TOut>(this Expression<Func<TIn, TOut>> proj, Expression<Func<TIn, TOut>> addProj = null) {
if (addProj != null) {
var pBody = ((MemberInitExpression)proj.Body);
var newBindings = new ReadOnlyCollection<MemberBinding>(pBody.Bindings.Concat(((MemberInitExpression)addProj.Body).Bindings).ToList());
var newBody = Expression.MemberInit(pBody.NewExpression, newBindings);
proj = (Expression<Func<TIn, TOut>>)Expression.Lambda(newBody, proj.Parameters);
}
return proj;
}
which reduces the GetEmployee body to:
public IQueryable<EmpDTO> GetEmployee(Expression<Func<Employee, EmpDTO>> addProj = null) {
Expression<Func<Employee, EmpDTO>> projection = emp => new EmpDTO {
Id = emp.Id,
Name = emp.Name,
Salary = emp.Salary,
};
if (addProj != null)
projection = projection.Add(addProj);
return entities.Employees.Where(e => e.Salary > 10000).Select(projection);
}

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

how to pass string variable to linq select new {} section

Ii just want to make search functionality with linq with multiple ColumnNames that stored to session variable. I'm using one method:
public void FillGrid(string CommandName,string ColumnName, string SearchText)
That has three string variable that stores session value.
Now I just want to pass ColumnName with this query:
var query1 = (from p in db.Posts
join c in db.Categories on p.Category_id equals c.Id
join u in db.Users on p.User_id equals u.Id
where (p.ToUser_id == user_id || p.ToUser_id == null) && p.User_id != user_id
orderby p.Sent_Datetime descending
select new
{
Id = p.Id,
Title = p.Title,
Publisher = u.First_name + " " + u.Last_name,
ToUser = p.ToUser_id,
PublishDate = p.Sent_Datetime,
IsFile = p.IsFileAttached,
CategoryName = c.Category_name,
status_name = (from s in db.Status where (s.Id == p.status_id) select s.status_name).FirstOrDefault(),
Group_name = (from g in db.Groups where (g.Id == p.group_id) select g.Group_name).FirstOrDefault(),
FileSize = p.TotalFileSize,
ColumnName = Sesssion["ColumnName"].ToString()
}).Where(q => q.ColumnName.Contains(SearchText));
However, ColumnName does not give any text or it may be not part of this query i have to manually give column name because.
for multiple column i have, so i can not use this statement like:
.Where(q => q.Tile.Contains(SearchText));
this query works fine with single column. but there is multiple column i have so i have to set q.ColumnName from outer side.
I would do an extension method for that kind of things, building an expression for your predicate.
public static class Helper
{
public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> queryable, string colName, string searchText)
{
if (colName != null && searchText != null)
{
var parameter = Expression.Parameter(typeof(T), "m");
var propertyExpression = Expression.Property(parameter, colName);
var searchExpression = Expression.Constant(searchText);
var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var body = Expression.Call(propertyExpression, containsMethod, searchExpression);
var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
return queryable.Where(predicate);
}
else
{
return queryable;
}
}
}
usage in your case
var query1 = (from p in db.Posts
join c in db.Categories on p.Category_id equals c.Id
join u in db.Users on p.User_id equals u.Id
where (p.ToUser_id == user_id || p.ToUser_id == null) && p.User_id != user_id
orderby p.Sent_Datetime descending
select new
{
Id = p.Id,
Title = p.Title,
Publisher = u.First_name + " " + u.Last_name,
ToUser = p.ToUser_id,
PublishDate = p.Sent_Datetime,
IsFile = p.IsFileAttached,
CategoryName = c.Category_name,
status_name = (from s in db.Status where (s.Id == p.status_id) select s.status_name).FirstOrDefault(),
Group_name = (from g in db.Groups where (g.Id == p.group_id) select g.Group_name).FirstOrDefault(),
FileSize = p.TotalFileSize,
}).FilterForColumn(Sesssion["ColumnName"].ToString(), SearchText);

Error in View when i try use inherit Linq magic

I try make table where i keep children-parent data. Ofc root of parents is "0" and here in table can by many roots. When i try make this work i got error.
Unable to create a constant value of type 'Projekty03.ViewsModels.ParagrafViewModel'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
public ViewResult Index()
{
List<ParagrafViewModel> _paragrafparent = new List<ParagrafViewModel>();
_paragrafparent.Add(new ParagrafViewModel { ParagrafID = 0, ParagrafNazwa = "Root" });
var _paragrafparent2 = from pr in paragrafRepository.All
orderby pr.ParagrafID
select new ParagrafViewModel
{
ParagrafID = pr.ParagrafID,
ParagrafNazwa = pr.ParagrafNazwa
};
var _paragrafparent3 = _paragrafparent.Concat(_paragrafparent2).AsEnumerable();
var paragraf = from par in paragrafRepository.All
join rodzic_p in _paragrafparent3
on par.ParagrafParent equals rodzic_p.ParagrafID
orderby par.ParagrafParent, par.ParagrafID
select new ParagrafViewModel
{
ParagrafID = par.ParagrafID,
ParagrafNazwa = par.ParagrafNazwa,
ParagrafParent = par.ParagrafParent,
ParagrafCzynny = par.ParagrafCzynny,
ParagrafWplyw = par.ParagrafWplyw,
ParagrafParentNazwa = rodzic_p.ParagrafNazwa
};
return View(paragraf);
}
I believe is sht wrong with my poor magic LINQ think. How resolve this ?
Ok here is a answer for my own question. Im sure is not a pretty solution but ...
public ViewResult Index()
{
List<ParagrafViewModel> _paragrafparent = new List<ParagrafViewModel>();
_paragrafparent.Add(new ParagrafViewModel { ParagrafID = 0, ParagrafNazwa = "Root", ParagrafCzynny=false, });
var _paragrafparent2 = from pr in paragrafRepository.AllIncluding(paragraf => paragraf.WniosekPodzial)
orderby pr.ParagrafID
select new ParagrafViewModel
{
ParagrafID = pr.ParagrafID,
ParagrafNazwa = pr.ParagrafNazwa,
ParagrafParent = pr.ParagrafParent,
ParagrafCzynny = pr.ParagrafCzynny,
ParagrafWplyw = pr.ParagrafWplyw,
WniosekPodzialNazwa = pr.WniosekPodzial.WniosekPodzialNazwa
};
var _paragrafparent3 = _paragrafparent.Concat(_paragrafparent2).AsEnumerable();
var paragrafModel = from par in _paragrafparent3
join rodzic_p in _paragrafparent3
on par.ParagrafParent equals rodzic_p.ParagrafID
orderby par.ParagrafParent, par.ParagrafID
select new ParagrafViewModel
{
ParagrafID = par.ParagrafID,
ParagrafNazwa = par.ParagrafNazwa,
ParagrafParent = par.ParagrafParent,
ParagrafCzynny = par.ParagrafCzynny,
ParagrafWplyw = par.ParagrafWplyw,
ParagrafParentNazwa = rodzic_p.ParagrafNazwa,
WniosekPodzialNazwa = par.WniosekPodzialNazwa
};
return View(paragrafModel);
}

group by base on 2 element

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();
...
}

Resources