ASP.NET MVC2 Posting a ViewModel mapping to Domain (LINQ) to Submitting changes - asp.net-mvc-2

I'm using AutoMapper to map between a Linq Domain object and a ViewModel to display an Edit Form to the user which works perfectly.
When they click submit I'd like to know the best way to map the ViewModel back to a Linq entity and persist it to the database.
The Linq entity I'm using has multiple collections of other entities (ie one-to-many references).
I was trying:
build up my custom view model using UpdateModel
get the previous state of the Linq entity by using the passed in id
map the view model onto the Linq entity (using automapper)
call SubmitChanges() on the data context
This method works when I'm only updating properties that are not collections, but throws errors when trying to modify properties that are collections.
Any help/thoughts would be much appreciated :)

I've taken an approach that is very similar to that used by Jimmy Bogard in the CodeCampServer project (http://codecampserver.codeplex.com/)
I have a general Mapper class that I inherit from where I just need to override a MapToModel method that maps from the ViewModel to the domain Model, and a GetIdFromViewModel method that returns the proper Id form the ViewModel so that the Service layer can grab the domain model from the database.
I had to change a little from the CodeCampServer examples because some of my Models used Guid and some used int as the Id for the Model.
You should be able to grab the code from the codeplex link above and that should help get you going in that direction.
Here is what one of my Mappers for a Member looks like:
public class MemberMapper : AutoFormMapper<Member, MemberFormViewModel, Guid>, IMemberMapper
{
public MemberMapper(IMemberService service) : base(service) { }
protected override Guid GetIdFromViewModel(MemberFormViewModel viewModel)
{
return viewModel.MemberId;
}
protected override void MapToModel(MemberFormViewModel viewModel, Member model)
{
// if the need arises, we will need to map the full objects as Foreign Key properties
// by using the proper repositories
// right now for loading the object to save back to the DB we don't have that need, so let's not waste the call
model.MemberId = viewModel.MemberId;
model.FirstName = viewModel.FirstName;
model.LastName = viewModel.LastName;
model.Title = viewModel.Title;
model.EmailAddress = viewModel.EmailAddress;
model.DirectPhone = viewModel.DirectPhone;
model.MobilePhone = viewModel.MobilePhone;
model.ElectronicId = viewModel.ElectronicId;
model.ProjectRoleTypeId = viewModel.ProjectRoleTypeId;
model.DepartmentId = viewModel.DepartmentId;
}
}
Then you can use this MemberMapper to map both directions. It uses AutoMapper to go from the domain Model to the View Model and then uses the MapToModel method that you implement to map from the View Model back to the domain Model.

Related

MEF exports that require remote data (like DB data) in order to be created

please excuse the long description at the beginning. the questions are at the end.
i have a windows service that is supposed to read data form some data sources (represented by the IDataSource interface).
i'm using MEF in my project and i was thinking of injecting the required data sources via ctor injection like below:
[Export(typeof(Service))]
public class Service:ServiceBase{
[ImportingConstructor]
public Service([ImportMany]IEnumerable<IDataSource> dataSources){
//...
}
}
However, there is a problem in doing it like this. The service needs to use any combination of data sources: multiple data sources of the same type (ex: 2 CSVDataSource instances) or multiple data sources of different types (ex: 2 CSVDataSource instances and 1 SQLDataSource instance).
Each data source has properties that are retrieved from the DB in order to properly set it up. these settings might indicate from where to read the data and at what intervals. this is why, in my implementation, the data sources have a ctor that accepts an id. this id is used to identify the data source in the DB and to retrieve the specific data source settings from the DB. this can be seen below.
public class CSVDataSource: IDataSource{
public CSVDataSource(int dsId){
//call web service in order to get properties to
//properly set up the data source.
}
//...
}
i feel that the service definition presented above is not suited for this scenario. The other approach I can think of is to use some sort of factory that allows the service to dynamically create the data sources inside. this implementation might look like below.
public class Service:ServiceBase{
[ImportingConstructor]
public Service(IDataSourceFactory dsFactory)
{
if (dsFactory == null) throw new ArgumentNullException("dsFactory");
IEnumerable<IDataSource> dataSources = dsFactory.CreateAll();
}
}
[Export(typeof(IDataSourceFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class DataSourceFactory:IDataSourceFactory
{
private readonly int agentId;
[ImportingConstructor]
public DataSourceFactory([Import("AgentId")]int agentId)
{
this.agentId = agentId;
}
public IEnumerable<IDataSource> CreateAll()
{
List<IDataSource> dataSources = new List<IDataSource>();
//access web service and instantiate the data sources
return dataSources;
}
}
And now to my questions:
is my factory approach a good ideea or should i look for another approach?
is it ok to have exports that require data from a remote location in order to be created?
Did you come across ExportMetadataAttribute before? It will allow you to assign metadata to an export that you can view before the export is created. You'll be able to import your IDataSources as Lazy and then should be able to create them yourself with the required parameters.
There's a good breakdown of Lazy and ExportMetadata here

EntityFramework with Repository Pattern and no Database

I have a web api project that I'm building on an N-Tier system. Without causing too many changes to the overall system, I will not be touching the data server that has access to the database. Instead, I'm using .NET remoting to create a tcp channel that will allow me to send requests to the data server, which will then query the database and send back a response object.
On my application, I would like to use entity framework to create my datacontexts (unit of work), then create a repository pattern that interfaces with those contexts, which will be called by the web api project that I created.
However, I'm having problems with entity framework as it requires me to have a connection with the database. Is there anyway I can create a full entity framework project without any sqlconnections to the database? I just need dbcontexts, which I will be mapping my response objects and I figure that EF would do what I needed (ie help with design, and team collabs, and provide a nice graphical designer); but it throws an error insisting that I need a connection string.
I've been searching high and low for tutorials where a database is not needed, nor any sql connection string (this means no localdb either).
Okay as promised, I have 3 solutions for this. I personally went with #3.
Note: Whenever there is a repository pattern present, and "datacontext" is used, this is interpreted as your UnitOfWork.
Solution 1: Create singletons to represent your datacontext.
http://www.breezejs.com/samples/nodb
I found this idea after going to BreezeJS.com's website and checked out their samples. They have a sample called NoDb, which allows them to create a singleton, which can create an item and a list of items, and a method to populate the datacontext. You create singletons that would lock a space in memory to prevent any kind of thread conflicts. Here is a tid bit of the code:
//generates singleton
public class TodoContext
{
static TodoContext{ }
private TodoContext() { }
public static TodoContext Instance
{
get
{
if (!__instance._initialized)
{
__instance.PopulateWithSampleData();
__instance._initialized = true;
}
return __instance;
}
}
public void PopulateWithSampleData()
{
var newList = new TodoItem { Title = "Before work"};
AddTodoList(newList);
var listId = newList.TodoListId;
var newItem = new TodoItem {
TodoListId = listId, Title = "Make coffee", IsDone = false };
AddTodoItem(newItem);
newItem = new TodoItem {
TodoListId = listId, Title = "Turn heater off", IsDone = false };
AddTodoItem(newItem);
}
//SaveChanges(), SaveTodoList(), AddTodoItem, etc.
{ ... }
private static readonly Object __lock = new Object();
private static readonly TodoContext __instance = new TodoContext();
private bool _initialized;
private readonly List<TodoItem> _todoLists = new List<TodoItem>();
private readonly List<KeyMapping> _keyMappings = new List<KeyMapping>();
}
There's a repository included which directs how to save the context and what needs to be done before the context is saved. It also allows the list of items to be queryable.
Problem I had with this:
I felt like there was higher maintenance when creating new datacontexts. If I have StateContext, CityContext, CountryContext, the overhead of creating them would be too great. I'd have problems trying to wrap my head around relating them to each other as well. Plus I'm not too sure how many people out there who agree with using singletons. I've read articles that we should avoid singletons at all costs. I'm more concerns about anyone who'd be reading this much code.
Solution 2: Override the Seed() for DropCreateDatabaseAlways
http://www.itorian.com/2012/10/entity-frameworks-database-seed-method.html
For this trick, you have to create a class called SampleDatastoreInitializer that inherits from System.Data.Entity.DropCreateDatabaseAlways where T is the datacontext, which has a reference to a collection of your POCO model.
public class State
{
[Key()]
public string Abbr{ get; set; }
public string Name{ get; set; }
}
public class StateContext : DbContext
{
public virtual IDbSet<State> States { get; set; }
}
public class SampleDatastoreInitializer : DropCreateDatabaseAlways<StateContext>
{
protected override void Seed (StateContext context)
{
var states = new List<State>
{
new State { Abbr = "NY", Name = "New York" },
new State { Abbr = "CA", Name = "California" },
new State { Abbr = "AL", Name = "Alabama" },
new State { Abbr = "Tx", Name = "Texas" },
};
states.ForEach(s => context.States.Add(s));
context.SaveChanges();
}
}
This will actually embed the data in a cache, the DropCreateDatabaseAlways means that it will drop the cache and recreate it no matter what. If you use some other means of IDatabaseInitializer, and your model has a unique key, you might get an exception error, where you run it the first time, it works, but run it again and again, it will fail because you're violating the constraints of primary key (since you're adding duplicate rows).
Problem I had with this:
This seems like it should only be used to provide sample data when you're testing the application, not for production level. Plus I'd have to continously create a new initializer for each context, which plays a similar problem noted in solution 1 of maintainability. There is nothing automatic happening here. But if you want a way to inject sample code without hooking up to a database, this is a great solution.
Solution 3: Entity framework with Repository (In-memory persistence)
I got this solution from this website:
http://www.roelvanlisdonk.nl/?p=2827
He first sets up an edmx file, using EF5 and the code generator templates for EF5 dbcontexts you can get from VS extension libraries.
He first uses the edmx to create the contexts and changes the tt templates to bind to the repository class he made, so that the repository will keep track of the datacontext, and provide the options of querying and accessing the data through the repository; in his website though he calls the repository as MemoryPersistenceDbSet.
The templates he modified will be used to create datacontexts that will bind to an interface (IEntity) shared by all. Doing it this way is nice because you are establishing a Dependency Injection, so that you can add any entity you want through the T4 templates, and there'd be no complaints.
Advantage of this solution:
Wrapping up the edmx in repository pattern allows you to leverage the n-tier architecture, so that any changes done to the backend won't affect the front end, and allows you to separate the interface between the front end and backend so there are no coupled dependencies. So maybe later on, I can replace my edmx with petapoco, or massive, or some other ORM, or switch from in-memory persistence to fetching data from a database.
I followed everything exactly as explained. I made one modification though:
In the t4 template for .Context.tt, where DbSetInConstructor is added, I had the code written like this:
public string DbSetInConstructor(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
“this.{1} = new BaseRepository();”,
_typeMapper.GetTypeName(entitySet.ElementType), entitySet);
}
Because in my case I had the entityset = Persons and entityname = Person. So there’d be discrepancy. But this should cover all bases.
Final step:
So whether you picked solution 1, 2, or 3. You have a method to automatically populate your application. In these cases, the stubs are embedded in the code. In my case, what I've done is have my web server (containing my front end app), contact my data server, have the data server query the database. The data server will receive a dataset, serialize it, and pass it back to the web server. The web server will take that dataset, deserialize it, and auto-map to an object collection (list, or enumberable, or objectcollection, etc).
I would post the solutions more fully but there's way too much detail between all 3 of these solutions. Hopefully these solutions would point anyone in the right direction.
Dependency Injection
If anyone wants some information about how to allow DI to api controllers, Peter Provost provides a very useful blog that explains how to do it. He does a very very good job.
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
few more helpful links of repository wrapping up edmx:
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
http://www.codeproject.com/Articles/688929/Repository-Pattern-and-Unit-of

Entity framework connection string reference from another project

I have a solution consisting of 4 projects. MVC, WCF, Business LYR, DataAcess. I am using entity framework for database transaction. My requirement is that i want to fetch the entity connectionstring only from MVC webconfig without refering in APP.cofig of acess layer. Is it possible in this scenario?
While I tried the following code I got an error.
this.ConnectionString="data source=cmh-sosql;initial catalog=Student;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";
System.Data.SqlClient.SqlConnectionStringBuilder scsb = new System.Data.SqlClient.SqlConnectionStringBuilder(this.ConnectionString);
EntityConnectionStringBuilder ecb = new EntityConnectionStringBuilder();
ecb.Metadata = "res://*/schoolModel.csdl|res://*/schoolModel.ssdl|res://*/schoolModel.msl";
ecb.Provider = "System.Data.SqlClient";
ecb.ProviderConnectionString = scsb.ConnectionString;
using (SchoolDB schoolDB = new SchoolDB(ecb.ConnectionString))
Error: The entity type student is not part of the model for the current context.
You are absolutely correct. I got the solution. There is no need to keep any string in webconfig for reference to a entity model. We can use the above code for reference it. But the change is to configure the context object.
public SchoolDB(string connectionString)
: base(connectionString)
{
}
We need to change the constructor also by this format.
thanks Sampath

Problem with EF STE and Self-Referencing tables

This is my first post here, so I hope everything is fine.
Here is my problem:
I have a table in my database called UserTypes. It has:
ID;
IsPrivate;
Parent_ID;
The relevant ones are the first and the third one.
I have another table called UserTypes_T which has information for the different types, that is language specific. The fields are:
Language_ID;
UserType_ID;
Name;
What I'm trying to achieve is load the entire hierarchy from the UserTypes table and show it in a TreeView (this is not relevant for now). Then, by selecting some of the user types I can edit them in separate edit box (the name) and a combo box (the parent).
Everything works fine until I try to persist the changes in the database. EF has generated for me two entity classes for those tables:
The class for the user types has:
ID;
IsPrivate;
Parent_ID;
A navigational property for the self-reference (0..1);
A navigational property for the child elements;
Another navigational property for the UserTypes_T table (1..*);
The class for the translated information has:
UserType_ID;
Language_ID;
Name;
A navigational property to the UserTypes table (*..1);
A navigational property to the Languages table (*..1);
I get the data I need using:
return context.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();
in my WCF Web service. I can add new user types with no problems, but when I try to update the old ones, some strange things happen.
If I update a root element (Parent_ID==null) everything works!
If I update an element where Parent_ID!=null I get the following error:
AcceptChanges cannot continue because the object’s key values conflict with another object in the ObjectStateManager.
I searched all over the internet and read the blog post from Diego B Vega (and many more) but my problem is different. When I change a parent user type, I actually change the Parent_ID property, not the navigational property. I always try to work with the IDs, not the generated navigational properties in order to avoid problems.
I did a little research, tried to see what is the object graph that I get and saw that there were lots of duplicate entities:
The root element had a list of its child elements. Each child element had a back reference to the root or to its parent and so on. You can imagine. As I wasn't using those navigational properties, because I used the IDs to get/set the data I needed, I deleted them from the model. To be specific I deleted points 4 and 5 from the UserTypes entity class. Then I had an object graph with each element only once. I tried a new update but I had the same problem:
The root element was updated fine, but the elements, that had some parents, threw the same exception.
I saw that I had a navigational property in the UserTypes_T entity class, pointing to a user type, so I deleted it too. Then this error disappeared. All the items in the object graph were unique. But the problem remained - I could update my root element with no problems, but when trying to update the children (with no exclusions) I got a null reference exception in the generated Model.Context.Extensions class:
if (!context.ObjectStateManager.TryGetObjectStateEntry(entityInSet.Item2, out entry))
{
context.AddObject(entityInSet.Item1, entityInSet.Item2);//here!
}
I tried to update only the name (which is in UserTypes_T) but the error is the same.
I'm out of ideas and I've been trying to solve this problem for 8 hours now, so I'll appreciate if someone gives me ideas or share their experience.
PS:
The only way I succeeded updating a child object was using the following code to retrieve the data:
var userTypes = argoContext.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();
foreach (UserType ut in userTypes)
{
ut.UserType1 = null;
ut.UserTypes1 = null;
}
return userTypes;
where UserType1 is the navigational property, pointing to the parent user type and UserTypes1 is the navigational property, holding a list of the child element. The problem here was that EF "fixups" the objects and changes the Parent_ID to null. If I set it back again, EF sets the UserTypes1, too... Maybe there is a way to stop this behavior?
OK everybody, I just found what the problem was and I'm posting the answer if anybody else encounters the same issue.
The problem was that I was making some validation on the server in order to see if there isn't a circular reference between the user types. So, my method on the server looked something like:
using (MyEntities context = new MyEntities())
{
string errMsg = MyValidator.ValidateSomething(context.UserTypes,...);
if (!string.IsNullOrEmpty(errMsg)) throw new FaultException(errMsg);
//some other code here...
context.UserTypes.ApplyChanges(_userType);//_userType is the one that is updated
context.UserTypes.SaveChanges();
}
The problem is that when making the validation, the context is filled and when trying to save the changes, there are objects with the same key values.
The solution is simple - to use different context for validating things on the server:
using (MyEntities validationContext = new MyEntities())
{
//validation goes here...
}
using (MyEntities context = new MyEntities())
{
//saving changes and other processing...
}
Another one can be:
using (MyEntities context = new MyEntities())
{
using (MyEntities validationContext = new MyEntities())
{
//validation
}
//saving changes and other processing...
}
That's it! I hope it can be useful to somebody!

entity framework ctp5 get unproxied entity

EF CTP 5. I have a single instance where I would like to get the unproxied entity. I can't seem to find a way to do this. I don't want to disable proxy creation all together, just need it for this one query. Can anyone help?
Here is a simple example:
var myEntity = DbContext.Entities.Find(1);
var unproxy = myEntity...?
I believe the only possibility is to create new instance of DbContext and turn proxy creation off just to execute this query. The reason is that DynamicProxy is type created in runtime which derives from your original entity type and adds tracking and lazy loading functionality. You can't strip the proxy away once you created it this way. Try this:
using (var context = new MyDbContext(connectionString))
{
((IObjectContextAdapter)context).ObjectContext.ContextOptions.ProxyCreationEnabled = false;
var myEntity = context.Entities.Find(1);
}
In Asp.Net Core you can use AsNoTracking().
Eg:
var blogs = context.Blogs
.AsNoTracking()
.ToList();
More info you can find here.