Why do I get odd AutoMapped results if I map directly from IEnumerable to IEnumerable? - asp.net-mvc

I am having a strange issue with AutoMapper.
If I do the following
//Get my entities from EF repository
var movements = _movementRepository.AllIncluding(movement => movement.Asset, movement => movement.Job,movement => movement.Asset.MinorEquipmentType);
var model = new List<AssetMovementDetail>();
foreach (var assetMovementDetail in movements)
{
model.Add(Mapper.Map<AssetMovementDetail>(assetMovementDetail));
}
This works perfectly and gives me the results if I expect.
If alternatively I change model to be generated like:
var model = Mapper.Map<List<AssetMovementDetail>>(movements);
The results are different and have the same total number of results but many of the results are duplicates of each other and others are missing. Am I doing something wrong? Is this not how it is supposed to work.

You need to map list to list, rather than automatically getting mapping from just one list...
Hence unpexpected berhaviour.
To see what I mean, please take a look into this posting: Mapping Lists using Automapper
Edit
Maybe you have the same issue that was answered over there? Extra iterations in a foreach in an AutoMapper map. Please take a look, maybe it solves, or gives you some ideas?
It also maybe related to lazy (deferred) loading in your initial linq statement.
Edit 2
Here is the code from my own project that does successfully what you trying to do:
var dbResources = _db.GetResourcesForBusiness();
var vmResources = Mapper.Map<IEnumerable<DBResource>, IEnumerable<VMResource>>(dbResources);
its a bit different format for one shot deal compared to what you're using, try to use this, see if it works for you.
Hope this helps!

Related

Telerik Kendo Chart : How to bind the chart to a string type

I've been stuggling for a moment and I'm unable to find anything related to that. I'm a total newbie with Kendo, and sadly I was not able to find anything that could help my question, documentation, forums and all of that : they haven't helped at all.
Situation :
I have a viewmodel in my ASP .NET app. I'm trying to make a chart out of one of the proripeties called "Type". This propriety represent a type of data - let's say fruits, like "Banana", "Apple" etc.
This type contains only and only one type at the time. It cannot contain something like "Apple and bananas". It's always a string, too.
This proriety is part of a larger model. But I'm only interested in this one.
Now, what I like to do :
I'd like to make a chart, using Kendo, from that propriety.
That means, I have to bind my chart to my model, and then, it will be able to know how many time some of those Types were used.
Like, example, If I have three objects :
Name : "Mjuzl"
Type : "Potato"
Name : "Uijqf"
Type : "Apple"
Name : "Zjli"
Type : Potato"
I'd like my char to count that my model used the type Potato twice, and the type Apple once.
I know how to get my datasource that contain all of the objects that use my model. (I have already used Kendo Grid just before but it's so simplier tbh) My issue right now, is that I have no idea - and I wasnt' able to find any - how to actually display what I want in my chart. I say it again, they are strings. I know how to get my datasource. I don't know how to actually show what I want to show. (Should I use columns ? sections ? I don't know)
Do I need to build a JSON from my controller that will ask the database to count ? Does Kendo is able to do it by it's own ? I'm so lost, I have no idea what Kendo is actually waiting for to make my chart working. The documentation isn't helping at all. I've been researching for a while, I haven't found anything that describes the exact same problem. And I've been searching for days.
Very badly drawn image I've done to put a picture on my problem :
I don't ask to do it for me, I ask for a path. A way to do it.
Thanks.
One way would be to create a view model specifically for your chart, and you can populate that view model based on your data.
Roughly (untested code - just to give you an idea), something like this:
public class MyChartViewModel
{
public int TypeCount { get; set; }
public string TypeName { get; set; }
}
and then in your read method for the chart where you are populating MyChartViewModel:
var myExistingDataModel = howeverYouGetYourDataHere;
var model = new MyChartViewModel();
var distinctTypes = myExistingDataModel.Select(x => x.Type).Distinct().ToList();
foreach (var distinctType in distinctTypes)
{
model.TypeCount = myExistingDataModel.Count(x => x.Type == distinctType);
model.TypeName = distinctType;
}
Finally ! I managed to do it !
For any future reference :
Based on G_P's answer, I used a LINQ request to count all of my types : Linq distinct - Count (don't forget to remove the .District() otherwise I won't work !)
Then, I did some debuging to see if I actually return my data, because nothing was showing in the chart. It did return my data and the right number.
The issue for this case was, I use
return Json(types.ToDataSourceResult(request, ModelState));
To return my data to my chart. But ! there is a little thing to know about Chart, they don't work like grids. You have to use a specific setup for showing your data if you use ToDataSourceResult : https://docs.telerik.com/aspnet-mvc/html-helpers/charts/data-binding (See "3) (Optional) Configure a Custom DataSource."), just change the call to your controller, and voilĂ  ! It worked !

How can you get the current View's Model name?

I would expect this to be asked/answered a hundred times, but the only answer I can find anywhere on the entire Internet is:
var currentModel = Model.GetType().Name;
This almost works but for example if the Model is defined as
#model Myproject.Model.User_info
Then the value of currentModel ends up as something like this:
User_info_23L7HGAFWLIUHI7GLIUBGFWAKHGI73I37GArwq
Do I really have to strip off everything starting with the penultimate underscore? Or is there a better way?
Per Jasen's comment on the question above, the answer I ultimately went with was this:
var currentModel = System.Data.Entity.Core.Objects.ObjectContext.GetObjectType(Model.GetType()).Name;
... this reliably produces the correct name of both models and viewmodels as they are defined by the developer.

Find an specific item in the master list of an split app by using oModel.createKey

I'm using a split app layout for editing and creating new employees. Therefore I do have a button "Add employee". After submitChanges is done, I want to find this new employee in the master list and select it.
I am using an event-bus for the communication between detail-controller and master-controller.
fnAfterSubmitChangesSuccess: function(sChanel, sEvent, oData) {
var oResponseData = oData.__batchResponses[0].__changeResponses[0].data;
var sBindingPath = oModel.createKey("/EmployeeSet", {Begda: oData.Begda, Endda: oData.Endda, Pernr: oData.Pernr}).replace(/:\s*/g, "%3A");
},
Is there a way to find the index of a specific listitem by the using binding-path. Or is there another way to solve this problem, instead of looping over the whole list a do a comparison?
I'm afraid the only way to find the index of a specific listItems by binding-path is to walk through the collection of list items. So, I'm afraid that a very plain and short answer would be "No".
It's quite easy though, code is not that lengthy, and it also shouldn't cost to much performance if you're not talking about humongous lists. You will have to walk through the list of items though. Once you have found the item with a binding to the context path you're looking for, you can select it using setSelectedItem, like so:
var list = this.getView().byId("list");
jQuery.each(list.getList(), function(idx, item) {
if (items.getBindingContext().getPath = sBindingPath) {
list.setSelectedItem(item);
}
});
Note: Do keep in mind that if you're working with OData services and are working with a so-called 'growing list', the entry you're looking for may not necessarily be in the list.
Apologies, wish I could give you a more pleasant answer.

EF4 - Self tracking entities and inheritance and eager loading

I know this has been asked before in several ways but none of the answers seem applicable to me - or correct - or current, so I'll try again.
I have a large model with several intstances of inherited entities. One example is a Timetable that contains a collection of TimetableEvents. There are several sub-types of TimetableEvent, such as an InterviewTimetableEvent, BreakTimetableEvent and an ExercisetimeTableEvent. ExerciseTimetableEvent has a relationship to an Exercise entity.
I need to use self-tracking entities as I'm using a WCF back end to serve up data to several WPF clients in a stateless fashion.
So, I need to eager load everything and I thought that self-tracking entities would automatically do this but it appears they dont.
So, to get a timetable I need to do something like this:
var tt = (from s in ESSDataContainer.Timetables
.Include("TimetableEvents")
where s.TimetableId == timetableid
select s).FirstOrDefault();
This will give me the TimetableEvents but not the Exercises that are related to the ExerciseTimetableEvents. Ive tried the following (and several other suggestions) without luck:
var tt = (from s in ESSDataContainer.Timetables
.Include("TimetableEvents")
.Include("ExerciseTimetableEvents.Exercise")
where s.TimetableId == timetableid
select s).FirstOrDefault();
Is there a solution to this?
If not I'll go back to normal context tracking and connect to the database from a local container rather than using WCF.
Cheers
It's a bit tricky, but possible:
var tt = (from s in ESSDataContainer.Timetables
where s.TimetableId == timetableid
select new
{
TimeTable = s,
Events = s.TimeTableEvents,
Exercise = s.TimeTableEvents.OfType<ExerciseTimetableEvents>()
.Select(ett => ett.Exercise)
}).Select(s => s.TimeTable)
.AsEnumerable()
.FirstOrDefault();
Clear as mud, but, hey: No magic strings! Also, it has the advantage that it actually works....
There is a Proposal for this issua at Microsoft Connect:. If you think this worthy you can vote for it.

Code re-use with Linq-to-Sql - Creating 'generic' look-up tables

I'm working on an application at the moment in ASP.NET MVC which has a number of look-up tables, all of the form
LookUp {
Id
Text
}
As you can see, this just maps the Id to a textual value. These are used for things such as Colours. I now have a number of these, currently 6 and probably soon to be more.
I'm trying to put together an API that can be used via AJAX to allow the user to add/list/remove values from these lookup tables, so for example I could have something like:
http://example.com/Attributes/Colours/[List/Add/Delete]
My current problem is that clearly, regardless of which lookup table I'm using, everything else happens exactly the same. So really there should be no repetition of code whatsoever.
I currently have a custom route which points to an 'AttributeController', which figures out the attribute/look-up table in question based upon the URL (ie http://example.com/Attributes/Colours/List would want the 'Colours' table). I pass the attribute (Colours - a string) and the operation (List/Add/Delete), as well as any other parameters required (say "Red" if I want to add red to the list) back to my repository where the actual work is performed.
Things start getting messy here, as at the moment I've resorted to doing a switch/case on the attribute string, which can then grab the Linq-to-Sql entity corresponding to the particular lookup table. I find this pretty dirty though as I find myself having to write the same operations on each of the look-up entities, ugh!
What I'd really like to do is have some sort of mapping, which I could simply pass in the attribute name and get out some form of generic lookup object, which I could perform the desired operations on without having to care about type.
Is there some way to do this to my Linq-To-Sql entities? I've tried making them implement a basic interface (IAttribute), which simply specifies the Id/Text properties, however doing things like this fails:
System.Data.Linq.Table<IAttribute> table = GetAttribute("Colours");
As I cannot convert System.Data.Linq.Table<Colour> to System.Data.Linq.Table<IAttribute>.
Is there a way to make these look-up tables 'generic'?
Apologies that this is a bit of a brain-dump. There's surely imformation missing here, so just let me know if you'd like any further details. Cheers!
You have 2 options.
Use Expression Trees to dynamically create your lambda expression
Use Dynamic LINQ as detailed on Scott Gu's blog
I've looked at both options and have successfully implemented Expression Trees as my preferred approach.
Here's an example function that i created: (NOT TESTED)
private static bool ValueExists<T>(String Value) where T : class
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
Expression value = Expression.Equal(Expression.Property(pe, "ColumnName"), Expression.Constant(Value));
Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(value, pe);
return MyDataContext.GetTable<T>().Where(predicate).Count() > 0;
}
Instead of using a switch statement, you can use a lookup dictionary. This is psuedocode-ish, but this is one way to get your table in question. You'll have to manually maintain the dictionary, but it should be much easier than a switch.
It looks like the DataContext.GetTable() method could be the answer to your problem. You can get a table if you know the type of the linq entity that you want to operate upon.
Dictionary<string, Type> lookupDict = new Dictionary<string, Type>
{
"Colour", typeof(MatchingLinqEntity)
...
}
Type entityType = lookupDict[AttributeFromRouteValue];
YourDataContext db = new YourDataContext();
var entityTable = db.GetTable(entityType);
var entity = entityTable.Single(x => x.Id == IdFromRouteValue);
// or whatever operations you need
db.SubmitChanges()
The Suteki Shop project has some very slick work in it. You could look into their implementation of IRepository<T> and IRepositoryResolver for a generic repository pattern. This really works well with an IoC container, but you could create them manually with reflection if the performance is acceptable. I'd use this route if you have or can add an IoC container to the project. You need to make sure your IoC container supports open generics if you go this route, but I'm pretty sure all the major players do.

Resources