I'm in the process of re-factoring and structuring a Win8 App Solution. I've been separating out my key components into their own projects. I have:
The main Win8 project which uses MVVMLight (and therefore SimpleIOC)
A Model project containing all my serialisable model classes
A Services project with various classes for navigation and serialisation
A Contracts project for all of my Interfaces
A View Models project containing the view models used by the main app.
So far I've got things working but have one case where I can't work out the best structure. Within my ViewModels project I have a data mapper class. Basically it takes in a model and spits out a view model. I've been trying to move this to the service layer and created an Interface for it but ran into a dependency within the Interface for knowledge of the ViewModel classes, so have essentially a circular dependency at the moment.
EDIT: I should explain that the ViewModels themselves need to utilise this mapper. For example I have an overall PageViewModel which holds everything the XAML page requires. One of these things is a list of VehicleViewModels which is a list of vehicles that contains some view specific properties. So the PageViewModel will call into the data service, get a Vehicle model and then use the mapper to turn this into the VehicleViewModel.
Here is the interface.
namespace MyApp.Contracts
{
public interface IDataMapperService
{
VehicleViewModel VehicleToVehicleViewModel(Vehicle v);
TripViewModel TripToTripViewModel(Trip t);
}
}
As you can see, I want to return a ViewModel object from the two methods. However the ViewModel project already has a reference to this Contracts project, so I this currently won't build.
I toyed with the idea of creating and Interface for the viewmodels but then I'd have lots of work to create the interfaces and I'm not sure that's the best way. Have I overlooked something obvious here?
EDIT: Here's an actual implementation of the current Interface:
public VehicleViewModel VehicleToVehicleViewModel(Vehicle v)
{
var newVehicle = new VehicleViewModel(v.VehicleID, v.Make, v.Model, v.Petrol, v.Registration);
foreach (Trip t in v.Trips)
{
newVehicle.Trips.Add(TripToTripViewModel(t));
}
IQueryable<Trip> trips = v.Trips.AsQueryable();
var now = DateTime.Now.Date;
var firstofmonth = new DateTime(now.Year, now.Month, 1);
while (now.DayOfWeek != DayOfWeek.Monday) now = now.AddDays(-1);
var weektrips = from t in trips
where t.Date >= now
select t;
var monthtrips = from t in trips
where t.Date >= firstofmonth
select t;
newVehicle.TripsThisWeek = weektrips.Count();
newVehicle.MilesThisWeek = (int)Math.Round(weektrips.Sum(t => t.Mileage), 0);
newVehicle.TripsThisMonth = monthtrips.Count();
newVehicle.MilesThisMonth = (int)Math.Round(monthtrips.Sum(t => t.Mileage), 0);
return newVehicle;
}
public TripViewModel TripToTripViewModel(Trip t)
{
var newTrip = new TripViewModel(t.TripID, t.Date, t.Mileage);
return newTrip;
}
You could use generics to create your mapper interface.
namespace MyApp.Contracts
{
public interface IDataMapperService<ViewModelT, ModelT>
{
ViewModelT ModelToViewModel(ModelT v);
}
}
Your service could then return an IDataMapperService<VehicleViewModel, Vehicle> and an IDataMapperService<TripViewModel, Trip>. You could create lightweight interfaces for view models and models to use with generic constraints.
namespace MyApp.Contracts
{
public interface IModel {}
public interface IViewModel {}
public interface IDataMapperService<ViewModelT, ModelT>
where ViewModelT : IViewModel
where ModelT : IModel
{
ViewModelT ModelToViewModel(ModelT v);
}
}
Then, to implement your new interface, you'd create a mapper class.
public class DataMapperService : IDataMapperService<VehicleViewModel, Vehicle>
{
public VehicleViewModel ModelToViewModel(Vehicle v)
{
//implementation goes here
}
}
Obviously, you will need to implement this class in a project that references your contracts, models, and viewmodels projects.
If I am understanding the question correctly you are trying to map from one object to a view model. If this is the case writing your own mapper tool may not be super efficiant for your usage. Check out Automapper It will allow you to map one object to another type by calling the Mapper.Map() method.
It looks to me like you are over thinking what you actually want to accomplish. If you need a VehicleViewModel then map the vehicle to the VehicleViewModel and call your mapping method. Automapper makes doing this super easy. But in general you just need a go-between mapper that lives on whatever layer can access your view models and it does the mapping for the different types.
Related
Can I use Mapster.Tool to generate Mappers without also generating the class that I'm mapping to? I have a typical Domain objects to and from DTOs scenario but the sample code here
https://github.com/MapsterMapper/Mapster/tree/master/src/Sample.CodeGen
and the documentation here
https://github.com/MapsterMapper/Mapster/wiki/Mapster.Tool
both focus on generating the DTOs from the Domain objects, either by annotating them with attributes or using configuration. There is configuration to create DTOs that are CRU specific but I'd still rather create my own DTOs but not have to create my own mappings.
Yes you can - take a look at the interface based code gen documented here.
This allows you to define an interface that will generate a mapper based on existing classes.
From there you can choose how to consume the mapper that's generated. Register in services and then use DI being one way.
Here is a quick example:
[Mapper]
public interface IContactMapper
{
ContactDetailVm MapTo(Contact contact);
}
Would result in
public partial class ContactMapper : IContactMapper
{
public ContactDetailVm MapTo(Contact p2)
{
return p2 == null ? null : new ContactDetailVm()
{
Id = p2.Id,
Created = p2.Created,
LastUpdate = p2.LastUpdate,
Title = p2.Title,
FirstName = p2.FirstName,
LastName = p2.LastName,
PreferredName = p2.PreferredName,
BirthYear = p2.BirthYear
};
}
}
I don't believe you can use the tool to generate the mapping extension methods for existing entities however. At least im not aware it can be done in v6.
I am working on a project which is currently at its initial stage so, I can make some architectural change at this point. This is more a design related issue. So here it is:
I am building a Web API + EF + .net framework + Repository pattern.
So I have a repository layer which return data from database context.following is snippet of linq in repository layer:
from custVerExt in _context.VERIFICATIONEXTs.Where(x => x.ID == custVer.ID).DefaultIfEmpty()
from zref_vcode in _context.LISTDATAs.Where(x => x.ID == custVerExt.VERIFICATIONCD).DefaultIfEmpty()
from refUi_vcode in _context.LBLTXTs.Where(x => x.ID == zref_vcode.REFLISTDATANMLBLID).DefaultIfEmpty()
from zref_tcode in _context.LISTDATAs.Where(x => x.ID == custVerExt.TYPEID).DefaultIfEmpty()
from refUi_tcode in _context.LBLTXTs.Where(x => x.ID == zref_tcode.REFLISTDATANMLBLID).DefaultIfEmpty()
Now here I want both the object refUi_vcode & refUi_tcode which is of type _context.LBLTXTs to be returned.
something like select refUi_vcode.name,refUi_tcode.name
I do not want my repository to return DTO's(its a job of my service layer) hence I want to return some customer domain object.
Now, I came up with two structures for my domain object. In case listed above, if I want to return value from the same table twice, I can create two instances of the same object OR create two separate properties which I want from those two objects.
Code sample:
public class CustDomainObj
{
public LBLTXTs obj1 {get;set;}
public LBLTXTs obj2 {get;set;}
}
//OR
public class CustDomainObj
{
public string obj1 {get;set;}
public string obj2 {get;set;}
}
My DTO look like this:
public CustDTO
{
public string vname{get;set;}
public string cname{get;set;}
}
Questions:
I am not sure if my repository - domain object return policy is the good bet in long run. If it is which way should I go? (Multiple instances of the same Entity object or just return required properties)
If I return required properties in the domain object, wouldn't it be a kind of DTO structure?
If both of my approaches are not correct, could anyone guide me with an appropriate example?
Thanks anyways!
I think that repository-domain object return policy is a good bet because :-
It will abide by separation of concerns (SoC) design principle i.e your repository layer will deal with domain objects and service layer with DTO.
Keeps the code unit testable so u can find if it breaks at repository or service layer.
If you use repository-domain object return policy, its better to just return required properties as there is no need of other properties of the Entity and would reduce redundancy.
And for your second question,there is a difference between DTO and domain objects. DTO are what may contain information required across different layers.Lets say your service layer requires to return a customers address details and work details(both are domain objects).Then the DTO will seem like this :-
DTO:-
public class CustDTO
{
public string address1{get;set;}
public string address2{get;set;}
public string company{get;set;}
public string location{get;set;}
}
Domain objects:-
public class CustAddress
{
public string address1{get;set;}
public string address2{get;set;}
}
public class CustWorkDetials
{
public string company{get;set;}
public string location{get;set;}
}
So basically DTO are used when u want to pass a single aggregate class of two or more classes of given layer as return value to layer above it in stack.
I'm a junior web developer trying to learn more every day.
What it the best practice for you guys to performe MVC repository pattern with Linq?
The one I use:
Create extra clases with the exact name of my .tt files with CRUD method like getAll(), getOne(), Update(), Delete() filling my own class with the entity framework and returning this, or using the entity framework crude
this is an example of what I'm actually doing.
this is my getAll method of my class for example User
public class CEmployee : CResult
{
public string name{get;set;}
public string lastname{get;set;}
public string address{get;set;}
//Extracode
public string Fullname // this code is not in the .tt or database
{
get
{
return name + lastname;
}
}
public <List>CEmployee getAll()
{
try
{
var result = (from n in db.Employee
select new CEmployee // this is my own class I fill it using the entity
{
name = n.name,
lastname = n.lastname,
address = n.address
}).ToList();
if (result.Count > 0)
{
return result;
}
else
{
return new List<CResult>
{
new CResult
{
has_Error = true,
msg_Error = "Element not found!!!!"
}
}
}
}
catch
{
return Exception();
}
}
}
that the way I do all thing I return a filled of my type, but on the web I see that people return the entity type normaly, But I do this to manipulate my response, And if I want to return extra information I just have to neste a list for example, whats the best way guys, return mytype or return the entity type ?
PD, I also use this class like my ViewModel.And I do this for all my classes.
One of the projects I am currently one uses Dependency Injection to setup the DAL (Data Access Layer.) We also are using an n-Tier approach; this separates the concern of the repository from the Business Logic and Front End.
So we would start with 4 or so base projects in the application that link to each other. One of that handles the Data Access, this would be your repository; read up on Ninject for more info on this. Our next tier is our Domain which houses the Entities built by the t4 template(.tt files) and also our DTO's (data transfer objects which are flat objects for moving data between layers.) Then we have a service layer, the service layer or business logic layer holds service objects that handle CRUD operations and any data manipulation needed. Lastly we have our front end which is the Model-View-ViewModel layer and handles the controllers and page building.
The MVVM calls the services, the service objects call the data access layer and Entity Framework works with Ninject to access the data and its stored in the DTO's as it is moved across layers.
Now this may seem overly complex depending on the application you are writing, this is built for a highly scalable and expandable web application.
I would highly recommend going with a generic repository implementation. The layers between your repository and the controller vary depending on a number of factors (which is kind of a broader/bigger topic) but the generic repository gets you going on a good implementation that is lightweight. Check out this article for a good description of the approach:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Ideally in a MVC application, you will want to repositories in a different layer like in a separate project, let's call it Data layer.
You will have an IRepository interface that contain generic method signatures like GetAll, GetById, Create or UpdateById. You will also have abstract RepositoryBase class that contain shared implementation such as Add, Update, Delete, GetById, etc.
The reason that you use an IRepository Interface is, there are contracts for which your inherited repository class, such as EmployeeRepository in your case, need to provide concrete implementations. The abstract class serves as a common place for your shared implementation (and override them as you need to).
So in your case, what you are doing using LINQ with your DbContext is basically correct, but implementation like your GetAll method should be part of the generic/shared implementation in your abstract class RepositoryBase:
public abstract class RepositoryBase<T> where T : class
{
private YourEntities dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected YourEntities DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual T GetById(long id)
{
return dbset.Find(id);
}
public virtual T GetById(string id)
{
return dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
}
}
I would suggest you need to think about whether or not to return an error result object like CResult, and think about if your CEmployee and CResult should exist in this parent-child relationship. Also think about what you want to do with your CResult Class. It seems to me your CEmployee handles too many tasks in this case.
I was wondering what is the best approach to having a select list on a form which contains values from a database without duplicating any code.
What I thought would make sense would be to load this data in the controller and pass it to a view model, so I can use SelectListFor<> or whatever in order to generate the list. However this means that I have to duplicate all the list loading in both the GET and the POST methods. The other way I can see would be to pass the database context into the view model constructor and have it load the list , but this then presents two more issues:
1) Should the view model know about the database context?
2) I then cannot use model binding by accepting the view model type as a method argument because it does not have a no-argument constructor (if I create a no-argument constructor then it won't have the lists if I want to redisplay the view containing the form).
Is there a better way to do this? This seems like it must be a fairly common scenario and any advice would be appreciated.
We typically implement our lookups through a ReferenceDataRepository that gets used within the controllers in the same way as any other repository interaction. This repository will usually recieve a high number of calls for predominantly static readonly data so we may implement a derived CachedReferenceDataRepository over this using an abstraction of your caching scheme of choice (Session, AppFabric etc).
Why not get you db or repository or business rule - whatever you call it send back an IDictionary???
This example assumes you have a list of users, you will send back an Key with their ID and the Value with lets say first name + last name:
Then use this inside the view....
<%= Html.DropDownListFor(model => model.UserID, new SelectList(Model.AvailableUsers, "Key", "Value",Model.UserID))%>
model.UserID = Key
Model.AvailableUsers = IDictionary<int,string>
I create my lists in some helper code sometimes then I lookup those values using this helper... so there is one centralized class (usually static) that will generate these "Users"...
Pass these users onto the view directly or alternatively a ViewModel as in your case- which is what I recommend
NOTE: You would not hookup your data context with the List/ Model Binding, that makes things too complex. Just take in the UserID as the selected user from the list then in your post handle apporpriately...
ViewModel:
public class UsersViewModel
{
public int UserID { get; set; }
public IDictionary<int,string> AvailableUsers{ get; set; }
}
In your post...
[HttpPost]
[ValidateAntiForgeryToken]
[DemandAuthorization(RoleNames.AdminUser, AlwaysAllowLocalRequests = true)]
public ActionResult AllUsers(int UserID)
{
try
{
//save to db or whatever...
return RedirectToAction("Index", "Users");
}
catch (RulesException ex)
{
ex.CopyTo(ModelState); //custom validation copied to model state
}
var _users= _service.GetUsers();
return View("AllUsers", new UsersViewModel
{
UserID = UserID,
AvailableUsers = _users
});
}
Well, in my opinion, you have to have context or repository object in your viewmodel to keep dry in this scenario. Furthermore, it is also correct that your viewmodel should not know about your database. To handle this issue you can have viewmodel's constructor accept an interface like
public Interface IUserRepository
{
public IEnumerable<User> GetAll();
}
and you can have your view model like
public class CreateVM
{
private IUserRepository _repo;
public CreateVM(IUserRepository repo)
{
_repo = repo;
}
public IEnumerable<SelectListItem> AvailableUsers
{
get{
return _repo.GetAll().Where(x=>x.isAvailable).Select(x=>new SelectListinItem{Text = x.UserName, Value = x.UserID});
}
}
}
Last piece of the puzzle is your DI setup. tell ur IOC container to inject IUserRepository in constructor of your viewmodel whenever it is instantiated. I don't know if DI can work when modelbinder creates an instance of your view model but it it does you are there at least in theory. your viewmodel does not know your repository but only an interface and your list is created at single point so you are dry too.
The biggest problem I see with passing IRepository to ViewModel is that this can easily cause performance issues - select n+1's are so natural in this case, that it is hard to avoid them. You want to have as little rountrips to DB as possible for the request, and having IRepository passed around all those multi-level ViewModels just doesn't help that.
Instead, you can introduce ViewModel factory which is responsible for creating ViewModels of desired type. MyViewModelFactory would depend on IRepository, and would create MyViewModel which is just plain DTO.
is this a common and/or good approach?
In my ViewModel(Wpf) or Presenter(WinForms) I do this:
ICustomerService customerService = MyService.GetService<ICustomerService>();
ICustomerList customerList = customerService.GetCustomers();
the CustomerService class looks like this:
public class CustomerService : ICustomerService
{
public ICustomerList GetCustomers()
{
return _customerDataProvider.GetCustomers();
}
}
public class CustomerDataProvider()
{
public ICustomerList GetCustomers()
{
// Open SQL connection,
// get back a SqlDataReader and iterate it
// in the loop write all data into a ICustomer object
// add the ICustomer object to the ICustomerList
// return ICustomerList object...
}
}
Retrieving data from a database is the plumbing of your application. And the less plumbing you have to write yourself, the more productive you will be.
I usually go to LINQ directly in the client:
sp_GetCustomersResult customers;
using (var db = new DbDataContext(ConnectionString))
customers = db.sp_GetCustomers();
This works fairly well, and lets me focus on adding customer value instead of database access layers.
I haven't found much value in declaring interfaces for business classes or for custom collections since extension methods became available. I would have GetCustomers return IEnumerable<Customer>.
If you plan on working extensively with business objects then you should look into using an object/relation mapper such as NHibernate. Or use LINQ2SQL or Entity Framework to reduce the amount of repetitive plumbing code you have to write.