making emitmapper aware of inheretance - emitmapper

I'm trying to make emitmapper aware of hierarchies in my objects so it can select the most derived mapping for a class. Say that I have these classes
public class Payment { }
public class GuaranteePayment : Payment { }
public class CreditCardPayment: GuaranteePayment { }
And their respective DTOs (PaymentDTO, GuaranteePaymentDTO, etc) and the object I want to map has a collection of Payment, where each can any of the types deriving from Payment, including Payment itself, while the target is a DTO of that object with a collection of PaymentDTO of course.
If I don't configure anything, emitmapper always creates and maps the base type. What is the best way to make it aware of the most derived type?

Related

What is the right design to have a spring Entity that is different than what the REST API returns?

Right now, I have an #Entity say Car that has a certain set of attributes. This gets persisted into a database.
Now, in the #RestController, if I want to accept a Car parameter except for certain properties, how do I do that? Right now, I am creating a different class called CarInput that is the same as Car minus those properties.
Again, for REST API response, same thing. If I want to return a Car but with a certain field removed. Right now I created CarResponse as a model.
Is there a cleaner way to do this?
I'd make the case that your external representation and your internal storage should hardly ever be identical. Sure, there'll be significant overlap, but your database and your API should be as independent from each other as possible.
I'd say it's a good practice to have separate domain models for the model and view layer (read: two different Car classes, in different packages). You can use a mapping framework like Dozer or MapStruct to map back and forth between these different entity types.
There are two common approaches to such problem.
Use #JsonIgnore on fields/getters that you want to exclude. However, this can lead to annotation hell or generally hard to read code.
#JsonIgnore
private String password;
Create a DTO class that data would be deserialized from or serialized to. What I mean is that when some user makes a POST request with a car definition, it would be deserialized by spring to CarDto and then parsed by you in the service layer to the Car object which you could save to a database. Similarly, Car object would be parsed to CarDto if the user asks for a data.
#GetMapping("/{userId}")
UserDto getUser(#PathVariable Long userId) {
return userService.getUser(userId);
}
#PostMapping
UserDto addUser(#RequestBody UserDto userDto) {
return userService.createUser(userDto);
}
This one, on the other hand, could lead to a situation where you sometimes use a Dto and sometimes the class itself. Because of that, consider parsing to/from CarDto only in the controller layer (unlike in the example above)
Also it's good to avoid creating two classes in one file. It makes hard to find a desired class afterwards.
You can still avoid of using a DTO class.
When you post Car object to controller your can control the wanted properties and operate on it.
For selecting fields to return as the response you can use json views.
Entity :
public Car {
private String color;
#JsonView(Views.Public.class)
private Integer weight;
// getters, setters
}
Controller :
#RestController
public CarController
#Autowired
private CarRepository carRepository;
#GetMapping("/{id}")
#JsonView(View.Public.class)
public Book get(#PathVariable Long id){
return carRepository.findOne(id);
}
#PostMapping
public Book update(#RequestBody Car car) {
// only properties we want to update
if(car.getColor() != null) {
// save in database or other operations
}
}
}
View :
public class Views {
public static class Public {
}
}
This way the controller's method "get" will send to client only "weight" property and "update" method will operate only on selected properties.

C#, MVC3, How to use the non-generic DBSet with a runtime defined type?

I'm new to MVC and the EF. My app is a simple code-first with several POCO classes and a DBContext like this:
public class ExpDefContext : DbContext
{
public DbSet<Experiment> Experiments { get; set; }
public DbSet<Research> Researches { get; set; }
...
The problem: I need to add to my data model an entity-set that its type is built at runtime from user input, meaning I have no idea of its data structure.
I read the non-generic Dbset class is made just for this, so I added to the context:
public DbSet Log { get; set; }
...and created a constructor for the context that accepts the runtime-type and sets the new Dbset:
public ExpDefContext(Type LogRecType)
{
Log = Set(LogRecType);
}
(the type by the way is built using Reflection.Emit).
In the controller I create the type (named LogRec) and pass it to a new DBContext instance. Then I create a LogRec instance and try to Add it to the database:
Type LogRec;
LogRec = LogTypeBuilder.Build(dbExpDef, _experimentID);
var dbLog = new ExpDefContext(LogRec);
var testRec = LogRec.GetConstructor(Type.EmptyTypes).Invoke(Type.EmptyTypes);
dbLog.Log.Add(testRec);
dbLog.SaveChanges();
and I get an exception from the dbLog.Log.Add(testRec):
The entity type LogRec is not part of the model for the current context
What am I doing wrong?
Is there a better way to do this (preferably without diving too deep into the Entity Framework)?
Thanks
I suspect that EF only reflects over the generic DbSet<T> properties in your derived DbContext and ignores any non-generic DbSet properties when the model is created in memory.
However, an alternative approach might be to use the Fluent API in OnModelCreating to add your dynamic type as an entity to the model.
First of all you can add a type to the model only when the model is built in memory for the first time your AppDomain is loaded. (A model is built only once per AppDomain.) If you had a default constructor of the context in addition to the overloaded constructor and had created and used a context instance using this default constructor your model would have been built with only the static types and you can't use the dynamic type as entity anymore as long as the AppDomain lives. It would result in exactly the exception you have.
Another point to consider is the creation of the database schema. If your type is unknown at compile time the database schema is unknown at compile time. If the model changes due to a new type on the next run of your application you will need to update the database schema somehow, either by recreating the database from scratch or by defining a custom database initializer that only deletes the LogRec table and creates a new table according to the new layout of the LogRec type. Or maybe Code-First Migrations might help.
About the possible solution with Fluent API:
Remove the DbSet and add a Type member instead to the context and override OnModelCreating:
public class ExpDefContext : DbContext
{
private readonly Type _logRecType;
public ExpDefContext(Type LogRecType)
{
_logRecType = LogRecType;
}
public DbSet<Experiment> Experiments { get; set; }
public DbSet<Research> Researches { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
entityMethod.MakeGenericMethod(_logRecType)
.Invoke(modelBuilder, new object[] { });
}
}
DbModelBuilder doesn't have a non-generic Entity method, hence dynamic invocation of the generic Entity<T> method is necessary.
The above code in OnModelCreating is the dynamic counterpart of...
modelBuilder.Entity<LogRec>();
...which would be used with a static LogRec type and that just makes the type as entity known to EF. It is exactly the same as adding a DbSet<LogRec> property to the context class.
You should be able to access the entity set of the dynamic entity by using...
context.Set(LogRecType)
...which will return a non-generic DbSet.
I have no clue if that will work and didn't test it but the idea is from Rowan Miller, member of the EF team, so I have some hope it will.

How to decouple repository and entities

This is a question on domain model design.
Let's say for a domain design involving users and groups, we have the following interfaces to implement:
interface IUser
{
string Name{get;}
DateTime DOB {get;}
}
interface IGroup
{
string Name {get;}
bool IsUserInGroup(IUser user); // #1
void IncludeUser(IUser user); // #2
void ExcludeUser(IUser user); // #3
}
interface IUserRepository
{
IUser Create(string name);
IUser GetByName(string name);
void Remove(IUser user);
void Save(IUser user);
}
interface IGroupRepository
{
IGroup Create(string name);
IGroup GetByName(string name);
void Remove(IGroup group);
void Save(IGroup group);
}
The tricky bit is to implement #1 #2 and #3 while keeping the entity classes (User, Group) decoupled from the repository classes (UserRepository, GroupRepository.)
Another technicality to consider is that most RMDB systems do not implement many-to-many relationships, and in practice there is always a separate table (say, UserGroupAssociation) to have records each associates a user and a group via foreign keys. I would like to hide this implementation detail from the domain interfaces and expose the equivalent logic through members #1 #2 and #3.
The effect of calling #2 and #3 should not persist until the group object in question has been saved (i.e. passed to the Save() method of the repository object)
How do you usually do it?
I don't do it. My Repository objects are tightly coupled to the root of the aggregate to which they relate, and (as kind of an aside) I don't bother making interfaces for my domain model objects unless I find I have a good reason to do so - do you have a particular reason to do this?
I've not come across any Repository examples which don't use the entity implementation type in the repository class (this one, for instance) and can't think of any real advantage of using an interface instead. Interfaces earn their keep for infrastructure components (like a Repository) by making it easier to mock out entire layers of the system when testing, you don't get the same type of advantage using interfaces for domain objects.
And to perhaps actually answer the question...
I never have a domain object access a Repository - the domain object after all is supposed to represent something in the domain in real life, and Repositories are infrastructure components that don't exist in real life, so why would a domain object know about one?
For the specific example of adding a User to a Group, I'd use a Service Layer class, and do this:
public class UserService
{
private readonly IGroupRepository _groupRepository;
private readonly IUserRepository _userRepository;
public UserService(
IGroupRepository groupRepository,
IUserRepository userRepository)
{
this._groupRepository = groupRepository;
this._userRepository = userRepository;
}
public void IncludeUserInGroup(string groupName, string userName)
{
var group = this._groupRepository.FindByName(groupName);
var user = this._userRepository.FindByName(userName);
group.IncludeUser(user);
this._userRepository.SaveChanges();
}
}
public class User
{
public void AddToGroup(Group group)
{
this.Groups.Add(group);
}
public void RemoveFromGroup(Group group)
{
this.Groups.Remove(group);
}
}
Some points to note:
To avoid lazy-loading large numbers of Users when adding a User to a Group I've moved the Group administration methods onto User - depending on how much behaviour you actually have for Group, you might even consider turning it into an enumeration rather than a class. Be aware that if you're using the Entity Framework POCO T4 Templates with FixupCollections, this will still lazy-load all the Users in a Group, but you can get around that in one way or another :)
The Service Layer class would implement a Create() method, the like of which you have on your Repositories. The Repositories would have an Add method, Find methods and a SaveChanges() method. Add would add an object created by the Service Layer to the object context.
All Repository classes would be set up to use the same underlying, request-scoped object context, so it wouldn't matter which one you call SaveChanges() on.
SaveChanges() would cause all changes which had happened to objects during that request to be saved, such as a User having a new Group's added to their Groups collection.
Finally, another good technique for decoupling entities from Repositories and other infrastructure components is Domain Events.

How to execute Queries with multiple models in Entity framework with Dependency Injection

I tried using Dependency Injection with Entity framework in my MVC application. In the project I have defined Generic Repository class for CRUD operations. There are concrete service classes for each model object. My Controller in Presentation layer uses Concrete classes of Service layer to get data from database. These concrete classes in turn calls RepositoryClass methods to implement actual operation with database.
Below is sample of the class definations (for simplicity I have removed various interfaces details and implementation of some methods):
class RepositoryBase<T>
{
Add(T entity) {...}
Update (T entity) {...}
Delete (T entity) {...}
T GetById(int id) {...}
IEnumerable<T> GetAll()
{dbContext.ToList();}
}
public class CarsService {
public IEnumerable<Cars> GetCars()
{
var cars = RepositoryBase<Cars>.GetAll();
return cars;
}
public Car GetCar(int id)
{
var car = RepositoryBase<T>.GetById(id);
return car;
}
}
Public class DealerService {...}
All this works great as long as I have to deal with 1 object type at a time in my application. But I am not sure how to make change in service class to get data for multiple entities i.e. Car and dealers togather. Please note in my scenario although i have dealer id defined in Cars model but navigation property is missing. So I have to join Cars and Dealers using linq query.
Please help to identify correct class (layer) which needs to be modified. All the examples I have found only talks about 1 entity at a time.
DbContext.Set().Include()first of all you put you config mapping for fixing,
second if you don't want to use navigation properties , you can use
RepositoryBase<Cars>.GetEntitySet<Cars>.Include("Dealers") //this does join if you key to join
but in this case you should use the
add to RepositoryBase<T> a property
public ISet<T> GetEntitySet<T>(string table2Include)
{
return DbContext.Set<T>()
}

MVC - Interface as Controller Action parameter

I want to pass one of a number of classes that implement an interface from my view back to my controller action. I use an ActionLink in my view passing the instance to my action, but it naturally fails because MVC cannot deal with interfaces via default model binding.
So :
<%=Html.ActionLink(flow.Source.Name, "Get", new {container=flow.Source})%>
is in a loop and each flow.Source conforms to IContainer.
public class Flow
{
public virtual IContainer Source { get; private set; }
}
public interface IContainer
{
//members here
}
public class File : IContainer
{}
public class Worksheet : IContainer
{}
Basically I want to call an action method :
public ActionResult Get(IContainer container)
{
// Do something
}
The reason being that I need to retrieve the state of the current container passed to my action method from the database. I use NHibernate and have entities mapped on a table per entity, so have one for File and one for Worksheet for example, so need to able to decide which data access class to use. Make sense? Probably not!
Can this be done without moving towards a base class Container? Can I stick with an interface being passed to my action method and resolve the subtype instance passed in place of the interface?
Any help with this would be gratefully appreciated.
An interface needs 'some' concrete implementation to reference when you would call your class. I think judging by your post you are aware of this : )
With that said there is 'kinda' of an approach handled here where you just create your own model binder that has to know about (or how) to map to and create a concrete type (either directly or by dependency injection)
ASP.NET MVC - Custom Model Binder on Interface Type

Resources