Using Linq to populate ViewModel from Model - c#

I am populating my viewmodels from linq queries. I have a method to retrieve a list of plans that looks something like this
public static IEnumerable<PlanViewModel> GetPlans()
{
using (var context = new RepEntities())
{
var query = (from p in context.Plans.Include("StatusCommon")
join r in context.RealEstateDetails on p.ReId equals r.ReId
select new PlanViewModel
{
PlanName = p.PlanName,
...
LastUpdated = p.LastUpdated,
});
return query.ToList();
}
}
Where you see the ellipses are about 30 other properties. Now I want to build a method to return a single Plan. The method would be virtually the same except that it will contain a where clause to specify a plan Id. I would like to refactor this code so that I am not duplicating the mapping of the Model to the ViewModel. However, I'm not finding a way that allows me to do this. Can anyone offer any suggestions as to how to properly code this so that here isn't so much duplication?
Thanks in advance!

Either use reflection to populate the fields, or go with a library like AutoMapper. I'd definitely recommend using AutoMapper though, it will keep your code a lot cleaner.
Another possibility is using implicit or explicit converters.
It pretty much depends where you want to have the code:
Utility class (reflection)
Models/ViewModels (implicit or explicit)
Anywere (AutoMapper)

Related

Correct method of casting to a strongly typed dataset

I have a WPF treeview that is loaded from a set of classes hierarchy (strongly-typed-dataset (Entity Framework).)
I am looking for the correct way to cast these nodes back as one of these objects.
At the moment I have to write code for each class within my hierarchy (This is an example of how I am deleting an object):
if (MainTree.SelectedItem is tblProject)
{
var s = (tblProject)MainTree.SelectedItem;
_context.tblProjects.Remove(s);
}
if (MainTree.SelectedItem is tblLine)
{
var s = (tblLine)MainTree.SelectedItem;
_context.tblLines.Remove(s);
}
if (MainTree.SelectedItem is tblDevice)
{
var s = (tblDevice)MainTree.SelectedItem;
_context.tblDevices.Remove(s);
}
I would like to know how I could reduce this code, and make it more flexible, so that I do not have to add code for each class that I might add in the future.
In case of EF you can use _context.Set(MainTree.SelectedItem.GetType()).Remove(MainTree.SelectedItem)
In general I would recomend to take a look into Data Binding and MVVM patttern to avoid the similar situations

OData dynamic template class

I am working with OData V3, and i came across this line:
var people = await client.For<People>().FindEntriesAsync();
In order for this to work, I need to define the People class, which has a bunch of set/get, which represent the fields I want.
Is there a simple and convenient way to avoid hard coding the structure classes? I want to be able to issue that command without having to define a specific "People" class. I would much rather have my results be in dictionary form, were the key's would be the column name, and the value would be the value in that column for the specific object.
Simple.OData.Client supports untyped scenarios, in which the CLR class is unnecessary.
For example:
var people = await client.For("People").FindEntriesAsync();
Then, people is a dictionary instance that you can use IDictionary<string, object> to refer. Thanks.
I don't think there is a way to avoid define a class like People, but if you really want to do this, you can try un-typed feature in OData.
Simple.OData.Client supports typed, untyped and dynamic scenario. So you can rewrite your query like this:
var x = ODataDynamic.Expression;
var people = await client.For(x.People).FindEntriesAsync();
here is another example:
var person = await client
.For(x.People)
.Filter(x.FirstName == "John")
.Select(x.LastName)
.FindEntryAsync();

How can I convert a list of domain objects to viewmodels on the Controller in ASP.NET MVC

I'd like to know the best way of converting a list of domain object I retrieve into custom ViewModels in the controller
e.g.
IList<Balls> _balls = _ballsService.GetBalls(searchCriteria);
into
IList<BallViewModels> _balls = _ballsService.GetBalls(searchCriteria);
it doesn't have to be exactly as I've outlined above i.e. it doesn't have to be an IList and if not accessing the service directly and instead go thru some other layer that converts the objects to viewmodels then that is ok too.
thanks
For simple objects you could just use Linq:
IList<BallViewModel> _balls = _ballsService.GetBalls(searchCriteria)
.Select(b => new BallsViewModel
{
ID = b.ID,
Name = b.Name,
// etc
})
.ToList();
That can get pretty repetitive though, so you may want to give your BallViewModel class a constructor that accepts a Ball and does the work for you.
Another approach is to use a library like AutoMapper to copy the properties (even the nested ones) from your domain object to your view model.
Probably a bit of Linq, something along the lines of
var ballQuery = from ball in _ballsService.GetBalls(searchCriteria)
select new BallViewModels
{
Diameter = ball.Diameter,
color = ball.Color,
...
}
IList<BallViewModels> _balls = ballQuery.ToList();
Either that or the question is more complicated than I think...
I use AutoMapper to do this all the time. It's really flexible and has worked for me without any troubles so far.
First you set up a map like during your app's initialization:
Mapper.CreateMapping<Balls, BallViewModel>();
And whenever you need to map the objects, you would do this:
Mapper.Map<IList<Balls>, IList<BallViewModel>>(_ballsService.GetBalls());
Like I said, it's very flexible and you can modify how the mapping happens for each property using a fluent API.

Dynamic "WHERE" like queries on memory objects

What would be the best approach to allow users to define a WHERE-like constraints on objects which are defined like this:
Collection<object[]> data
Collection<string> columnNames
where object[] is a single row.
I was thinking about dynamically creating a strong-typed wrapper and just using Dynamic LINQ but maybe there is a simpler solution?
DataSet's are not really an option since the collections are rather huge (40,000+ records) and I don't want to create DataTable and populate it every time I run a query.
What kind of queries do you need to run? If it's just equality, that's relatively easy:
public static IEnumerable<object[]> WhereEqual(
this IEnumerable<object[]> source,
Collection<string> columnNames,
string column,
object value)
{
int columnIndex = columnNames.IndexOf(column);
if (columnIndex == -1)
{
throw new ArgumentException();
}
return source.Where(row => Object.Equals(row[columnIndex], value);
}
If you need something more complicated, please give us an example of what you'd like to be able to write.
If I get your point : you'd like to support users writting the where clause externally - I mean users are real users and not developers so you seek solution for the uicontrol, code where condition bridge. I just though this because you mentioned dlinq.
So if I'm correct what you want to do is really :
give the user the ability to use column names
give the ability to describe a bool function (which will serve as where criteria)
compose the query dynamically and run
For this task let me propose : Rules from the System.Workflow.Activities.Rules namespace. For rules there're several designers available not to mention the ones shipped with Visual Studio (for the web that's another question, but there're several ones for that too).I'd start with Rules without workflow then examine examples from msdn. It's a very flexible and customizable engine.
One other thing: LINQ has connection to this problem as a function returning IQueryable can defer query execution, you can previously define a query and in another part of the code one can extend the returned queryable based on the user's condition (which then can be sticked with extension methods).
When just using object, LINQ isn't really going to help you very much... is it worth the pain? And Dynamic LINQ is certainly overkill. What is the expected way of using this? I can think of a few ways of adding basic Where operations.... but I'm not sure how helpful it would be.
How about embedding something like IronPython in your project? We use that to allow users to define their own expressions (filters and otherwise) inside a sandbox.
I'm thinking about something like this:
((col1 = "abc") or (col2 = "xyz")) and (col3 = "123")
Ultimately it would be nice to have support for LIKE operator with % wildcard.
Thank you all guys - I've finally found it. It's called NQuery and it's available from CodePlex. In its documentation there is even an example which contains a binding to my very structure - list of column names + list of object[]. Plus fully functional SQL query engine.
Just perfect.

Pros & cons between LINQ and traditional collection based approaches

Being relatively new to the .net game, I was wondering, has anyone had any experience of the pros / cons between the use of LINQ and what could be considered more traditional methods working with lists / collections?
For a specific example of a project I'm working on : a list of unique id / name pairs are being retrieved from a remote web-service.
this list will change infrequently (once per day),
will be read-only from the point of view of the application where it is being used
will be stored at the application level for all requests to access
Given those points, I plan to store the returned values at the application level in a singleton class.
My initial approach was to iterate through the list returned from the remote service and store it in a NameValueCollection in a singleton class, with methods to retrieve from the collection based on an id:
sugarsoap soapService = new sugarsoap();
branch_summary[] branchList = soapService.getBranches();
foreach (branch_summary aBranch in branchList)
{
branchNameList.Add(aBranch.id, aBranch.name);
}
The alternative using LINQ is to simply add a method that works on the list directly once it has been retrieved:
public string branchName (string branchId)
{
//branchList populated in the constructor
branch_summary bs = from b in branchList where b.id == branchId select b;
return branch_summary.name;
}
Is either better than the other - is there a third way? I'm open to all answers, for both approaches and both in terms of solutions that offer elegance, and those which benefit performance.
i dont think the linq you wrote would compile, it'd have to be
public string branchName (string branchId)
{
//branchList populated in the constructor
branch_summary bs = (from b in branchList where b.id == branchId select b).FirstOrDefault();
return branch_summary == null ? null : branch_summary.name;
}
note the .FirstsOrDefault()
I'd rather use LINQ for the reason that it can be used in other places, for writing more complex filters on your data. I also think it's easier to read than NameValueCollection alternative.
that's my $0.02
In general, your simple one-line for/foreach loop will be faster than using Linq. Also, Linq doesn't [always] offer significant readability improvements in this case. Here is the general rule I code by:
If the algorithm is simple enough to write and maintain without Linq, and you don't need delayed evaluation, and Linq doesn't offer sufficient maintainability improvements, then don't use it. However, there are times where Linq immensely improves the readability and correctness of your code, as shown in two examples I posted here and here.
I'm not sure a singleton class is absolutely necessary, do you absolutely need global access at all times? Is the list large?
I assume you will have a refresh method on the singleton class for when the properties need to change and also that you have some way of notifying the singleton to update when the list changes.
Both solutions are viable. I think LINQ will populate the collection faster in the constructor (but not noticeably faster). Traditional collection based approaches are fine. Personally, I would choose the LINQ version if only because it is new tech and I like to use it. Assuming your deployment environment has .NET 3.5...
Do you have a method on your webservice for getting branches by Id? That would be the third option if the branch info is needed infrequently.
Shortened and workified:
public string BranchName(string branchId)
{
var bs = branchList.FirstOrDefault(b => b.Id == branchId);
return bs == null ? null : bs.Name;
}

Categories

Resources