ValueInjecter with IQueryable<T> - asp.net-mvc

I need to map IQueryable<User> to IQueryable<SimpleUser> with ValueInjecter.
Is this possible?
I tried:
return userRepo.GetUsers()
.Select(o => new SimpleUser().InjectFrom(o))
.Cast<SimpleUser>();
But this cannot be translated to a stored expression...well, the method InjectFrom.
Can automapper do this?
I want something similar to this:
return from i in userRepo.GetUsers()
select new SimpleUser{
i.UserId,
i.Name
};
but with using some kind of mapper tool.

Convert the collection to objects before doing the select and it should work. Updated using PredicateBuilder to show filtering and paging and Dynamic LINQ for sorting.
var predicate = new PredicateBuilder<User>.True();
if (!string.IsNullOrEmpty( typeFilter ))
{
predicate = predicate.And( u => u.Type == typeFilter );
}
if (!string.IsNullOrEmpty( nameFilter ))
{
predicate = predicate.And( u => u.Name.StartsWith( nameFilter ));
}
// assumes sortColumn matches one of your user properties and
// sortDirection is either "ASC" or "DESC"
string sortOrder = string.Format( "{0} {1}", sortColumn, sortDirection );
return userRepo.GetUsers()
.Where( predicate )
.OrderBy( sortOrder )
.Skip( (page-1) * usersPerPage )
.Take( usersPerPage )
.ToList() // force the query and make these objects
.Select(o => new SimpleUser().InjectFrom(o))
.Cast<SimpleUser>();

Related

Orderby clause not working with drop down list in mvc

I am populating a drop down list using Linq and the orderby clause doesn't seem to work.
public List<Hello> getManagers()
{
var que = (from man in db.Table1
where man.Role == "Manager"
orderby man.Name
select new Hello
{
Managers = man.Name
}).Distinct().ToList();
return que;
}
Controller Class:
public ActionResult Index()
{
rp = new RequestProcess();
ViewBag.ID = fillSelectedList("", "ID", rp);
ViewBag.Managers = fillSelectedList("", "Managers", rp);
return View(""); //View 1
}
public static List<SelectListItem> fillSelectedList(string selValue, string type, RequestProcess rp )
{
List<SelectListItem> list = new List<SelectListItem>();
SelectListItem obj = new SelectListItem();
if (type == "Managers") {
var tempList= rp.getManagers();
tempList.ForEach(x =>
{
obj = new SelectListItem();
obj.Text = x.Managers;
obj.Value = x.Managers;
obj.Selected = x.Managers == selValue ? true : false;
list.Add(obj);
});
}
return list;
}
I am still receiving an un-ordered list. Any fixes?
The result is not ordered, because method Distinct does not return ordered results. What you need to do instead is to first call Disctinct, and only then OrderBy:
var que = (from man in db.Table1
where man.Role == "Manager"
select new Hello
{
Managers = man.Name
}).Distinct() // <- First distinct ...
.OrderBy(x => x.Managers) // <- ... then order by
.ToList();
As mentioned in the answer above, you need to sort the result after Distinct().
Also note that you are mixing Lambda expression and LINQ to Entities Queries... you may want to consider choosing one of them for consistency (though there is no syntax error if you mix them). This is the same query using lambda expression:
var que = _context.Table1
.Where(m => m.Role == "Manager")
.Select(h => new Hello { Managers = h.Name })
.Distinct()
.OrderBy(o => o.Managers)
.ToList();

how to return selected columns based on user choice

I'm trying to limit which fields are returned by an API based on a parameter called fields which I accept multiple strings doing this
private readonly string[] fields;
public string[] SelectiveSerializer(string fields)
{
string[] _fields;
var fieldColl = fields.Split(',');
_fields = fieldColl
.Select(f => f.ToLower().Trim())
.ToArray();
return _fields;
}
I want to be able to choose what I return based on whatever the user gives me in _fields. Normal way to do it:
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
ID = entity.ID,
FirstName = entity.FirstName,
LastName =entity.LastName,
FotherName = entity.FotherName
}).ToList();
but here I have to specify the fields in Select (ID, FirstName ..etc), which I want it to be dynamic based on what fields[] has. Is there a way to do this?
sort of this (which is wrong):
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
foreach (string s in _fields)
{
entity.s;
}
}).ToList();
Use a ternary expression for each assignment
var user = entityContext.Users.Where(u => u.ID == id)
.Select(u => new {
ID = _fields.Contains['id'] ? u.ID : 0,
FirstName = _fields.Contains['firstname'] ? u.FirstName : null,
LastName = _fields.Contains['lastname'] ? u.LastName : null,
otherName = _fields.Contains['othername'] ? u.otherName : null
})
.ToList();
I also would put the field names in a HashSet<string> for a better performance.
var _fields = new HashSet<string>(fields.Split(',').Select(f => f.ToLower().Trim()));
This solution keeps all the properties but sets the unwanted ones to null. If you want to dynamically add properties, see this other SO question: How to dynamically create a class in C#?. But note that this only useful in scenarios where objects of this type are processed dynamically as well.
I was finally able to do this with minimal work.
assuming the filter is a string list. string array.
so to avoid reflection and all that jazz, I iterate over each record and see if the variable is in the filter list, then create a dic entry with (var,val) assuming that no duplicate var in the same record, which can be catch if you want but I don't have this issue.
Then at the end add that dic to a list.
the method accept anonymous type list and a filter list.
public static List<Dictionary<string, object>> filteredList(IEnumerable source, string[] filter)
{
var filteredList = new List<Dictionary<string, object>>();
foreach (var single in source)
{
var type = single.GetType();
var props = type.GetProperties();
var singleRecord = new Dictionary<string, object>();
foreach (var v in props)
{
if (filter.Contains(v.Name))
{
var tempValue = type.GetProperty(v.Name).GetValue(single, null);
singleRecord.Add(v.Name, tempValue);
}
}
filteredList.Add(singleRecord);
}
return filteredList;
}

Dynamically apply filters on Entity Framework's entity using lambda expression

I need to have a method like this, where I can apply Where(x =>x. ...) and Include(x => x.RelatedEntity) and OrderBy(x=>x. ...) on a given entity.
Something like this:
public List<TEntity> ApplyFilter<TEntity>(TEntity entity,
List<filters> filters /* List of filters: 'filters' */)
where TEntity : BaseEntity
{
using (var db = new MyDbContext()){
var query = db.Set<TEntity>().AsQueryable;
//apply filters to 'query'
query.include(/*multiple related entities*/);
query.applyfilters(/*filters*/);
return query.ToList();
}
}
And I need to pass what I need to be filtered/included as lambda expressions.
NOTE: I searched a lot about how I can do it but I really wasn't able to find anything. I'm new to this part of C# / Entity Framework and I really didn't even know what keywords to search for.
Thank you for the help
You'll want to use a LINQ expression
public List<TEntity> ApplyFilter<TEntity>(
Expression<Func<TEntity, bool>> filter,
Expression<Func<TEntity, object>> orderBy,
params Expression<Func<TEntity, object>>[] includes) where TEntity : BaseEntity
{
using (var db = new MyDbContext())
{
var query = db.Set<TEntity>().AsQueryable();
query = query.Where(filter);
query = query.OrderBy(orderBy);
if (includes != null)
{
foreach (var include in includes)
{
query = query.Include(include);
}
}
return query.ToList();
}
}
To use the method:
ApplyFilter<TestObject>(
x => x.Prop1 == "foo",
x => x.Prop2,
x => x.Prop3, x => x.Prop4);
Like this?
var result = Repository.PurchaseProposalItem.GetDbSet();
if (filters.FilterByBrand) result = result.Where(p => p.GS_Product.GS_ProductBrand.PBr_Id == filters.BrandId);
if (filters.FilterByFamily) result = result.Where(p => p.GS_Product.GS_ProductFamily.PFa_Id == filters.FamilyId);
if (filters.FilterBySubFamily) result = result.Where(p => p.GS_Product.GS_ProductSubFamily.PSu_Id == filters.SubFamilyId);
if (filters.FilterByProductType) result = result.Where(p => p.GS_Product.Pro_Type == filters.ProductTypeEnum);
return result;

How to dynamically pass .Include & .Select

I am working on an asp.net mvc5 web application , with EF-6. I am trying to dynamically pass .Include & .Select as follow:-
var query = context.SecurityRoles.AsQueryable();
foreach (var include in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(include);
}
return await query
.SingleOrDefaultAsync(a2 => a2.SecurityRoleID == id);
}
which i will be calling as follow:-
var securityrole = await uniteofwork.SecurityRoleRepository
.FindSecurityRole(id.Value, "SecurityRoleModulePermissions.Select(a2=>a2.Module),SecurityRoleModulePermissions.Select(a2=>a2.PermissionLevel)),Staffs");
But the i am getting the following exception:-
A specified Include path is not valid. The EntityType
'SkillManagementModel.SecurityRoleModulePermission' does not declare a
navigation property with the name 'Select(a2=>a2'
You can include your navigation properties dynamically like this:
public async Task<SecurityRole> FindSecurityRole(Expression<Func<SecurityRole, bool>> predicate, params Expression<Func<SecurityRole, object>>[] includeProperties)
{
var query = context.SecurityRoles.AsQueryable();
if (includeProperties != null)
query = includeProperties.Aggregate(query, (current, include) => current.Include(include));
return await query.SingleOrDefaultAsync(predicate);
}
var securityrole = await uniteofwork.SecurityRoleRepository.FindSecurityRole
(sr => sr.Id == id.Value, sr => sr.Module, sr =>sr.PermissionLevel)

How to perform LINQ OrderBy based on a stringname for column

If I had
public ActionResult ListExpenseItems(long id)
{
IQueryable<I_ITEM> expenseItems = er.GetExpenseItems(id);
return PartialView(expenseItems );
}
and the LINQ
public IQueryable<I_ITEM> GetExpenseItems(long id)
{
return from i in db.I_ITEM
where i.ExpenseId == id
orderby i.ExpenseItemId ascending
select i;
}
If I passed a string in as a parameter to the LINQ method, say "ExpenseTitle", how would I do OrderBy i.ExpenseTitle so that orderby always matches the string parameter?
This kind of logic.. but actually correct:
db.I_ITEM.OrderBy(x => (orderBy == 'date') ? x.Date : (orderBy == 'id') ? x.Id : (orderBy == 'cost') ? x.Cost : x.Id);
I think this previous questions might solve your problem
Dynamic LINQ OrderBy
Strongly typed dynamic Linq sorting
or you can use the Dynamic Linq library.

Resources