I have a basic table with a few FK references. So when I retrieve an entity for an update operation; that entity contains ICollectionsof related entites. I also have a main ViewModel inside which each entity is a sub viewModel. My aim is to use Automapper like:
mapper.Map(MainViewmodel obj,MainEntity obj);
For this I have a MappingConfiguration like:
CreateMap<MainViewModel, MainEntity>();
CreateMap<subViewModel1, subEntity1>();
CreateMap<subViewModel2, subEntity2>();
This gives me an Unmapped properties exception because the ICollections are not getting mapped. Could anyone please guide me on the best way to deal with this kind of situation?
thanks.
If I understand you correctly, you has classes like this:
class MainViewModel
{
ICollection<SubViewModel1> SubViewModels { get;set; }
}
class SubViewModel1
{
}
and
class MainEntity
{
ICollection<SubEntity1> SubEntities { get;set; }
}
class SubEntity1
{
}
Then you should create rules for each class, and collection of such classes automaper map automatically.
CreateMap<MainViewModel, MainEntity>();
CreateMap<SubViewModel1, SubEntity1>();
Addditions 1:
Try this method: var mappedMainEntity = rmapper.Map<MainEntity>(MainViewmodel obj);
If you map MainEntity to MainViewModel you need add .ReverseMap() to map rule, like this:
CreateMap().ReverseMap();
CreateMap().ReverseMap();
Additions 2:
AutoMapper mapping public Properties only
If the mapping Properties have different names, you need to use explicitly indicating how to map these Properties. Using ForMember method and MapFrom option. Example
Related
Our project has a framework and an own code base, which implements entities of the framework.
The idea is also to have several indexes in the framework that will return the results of all inheritances of certain framework types like user.
Apparantly, the only way Raven supports this (without creating the index on the highest level and manually adding maps) is to store all objects in the same collection by overwriting the Clr-type. However, this means we lose the derived information and cannot query on it.
Some samples:
class A {
public string Id {get; set; },
public string Name {get; set; }
}
class B : A { }
class C : A { }
class D : C { }
Then I want to query something along the lines of:
store.Query<IndexOfA>().Where(a => a.Name == "foo").As<A>().ToList();
AND be able to still do this;
store.Query<IndexOfC>().As<C>().ToList()
My idea was to add a convention that saves both the derived and the base class to the metadata when storing documents in RavenDB, but I have no idea how to go about this and cannot find any documentation on the subject.
Any ideas?
You can create an index that used a multi map index with AddMapForAll<Base>, which will generate a separate entry for each derived class.
You could then use that index to do polymorphic queries.
I have an EntityFramework model with attributes, which I use to validate the fields.
private person tipProvider;
[Required]
[ForeignKey("TipProviderId")]
public virtual person TipProvider
{
get { return tipProvider; }
set
{
tipProvider = value;
ValidateProperty(MethodBase.GetCurrentMethod().Name.Replace("set_", ""));
raisePropertyChanged(MethodBase.GetCurrentMethod().Name.Replace("set_", ""));
}
}
I get the PropertyInfo and then its validation attributes, which I use to validate the property:
public virtual void ValidateProperty(string property)
{
errors[property].Clear();
var propertyInfo = this.GetType().GetProperty(property);
var propertyValue = propertyInfo.GetValue(this);
var validationAttributes = propertyInfo.GetCustomAttributes(true).OfType<ValidationAttribute>();
foreach (var validationAttribute in validationAttributes)
{
if (!validationAttribute.IsValid(propertyValue))
{
errors[property].Add(validationAttribute.FormatErrorMessage(string.Empty));
}
}
raiseErrorsChanged(property);
}
When the property is virtual, I cannot find the attributes via reflection. If the virtual keyword is removed, the attributes are found.
I'm really confused by this behavior. Why can't attributes be applied on virtual properties?
I do not know exactly what are you trying to do, but from what I know from EntityFramework, the problem is not exactly what you are thinking. You CAN apply attributes to virtual properties, and it is possible to recover them via reflection without any problem, just the way you are doing.
But on EF entities, when you mark a property as virtual, you are defining to the EF that the property is a navigation property (a property used to access foreign key data in a relationship, and retrieve it as child Entities).
Then, when you get a new instance of this entity from the database context at runtime, and access that property, EF will create a new class (dynamic proxy) derived from your class and uses it instead of your original class. Entity Framework does it to maintain the concept of "Lazy Loading" your relationships - avoiding loading an entire new dependent entity tree without being needed.
Because EF makes a new class derived from your Entity, AND the property is being overriden by that, your attribute is not being inherited by it.
You can see more about virtual marks and Navigation properties on this post.
In a DDD approach, I have a Domain Model (DM), with a rich behaviour. Suppose I have a root entity, called Order and relative LineOrder. The exposed collection of LineOrder need to be a IReadOnlyCollection since none can alter the collection arbitrarily. In code:
public class Order : AggregateRoot {
// fields
private List<LineOrder> lineOrder;
// ctors
private Order() {
this.lineOrder = new List<LineOrder>();
// other initializations
}
// properties
public IReadOnlyCollection<LineOrder> LineOrder {
get
{
return lineOrder.AsReadOnly();
}
}
// behaviours
}
So far, so good. But when I want to persist this domain I have some technology restrictions imposed by Entity Framework (a key is needed even if I have a value object, a parameterless constructor and so on) that is not a perfect match with a DDD approach.
Another limitation that I have is:
public class OrderConfiguration : EntityTypeConfiguration<Order>
{
public OrderConfiguration()
{
ToTable("Order");
HasMany<LineOrder>(m => m.LineOrder); // Exception: Cannot convert from IReadOnlyCollection to ICollection
}
}
I cannot cast IReadOnlyCollection to ICollection (incidentally, if LineOrder was an ICollection everything was OK!).
For the reasons I have expressed above: could be usefull in this case create a Persistence Model (with belonging cons: mapping DM/PM and viceversa)?
Are there an alternative? And, above all: are there an alternative that well fit a DDD approach?
Have you tried declaring the LineOrder collection as protected? This way EF has access but consumers do not.
// properties
protected ICollection<LineOrder> LineOrder { get; set; }
You can then expose this collection in a read-only manner to the end user with:
public IReadOnlyCollection<LineOrder> ReadOnlyLineOrder
{
get
{
return LineOrder.ToList().AsReadOnly();
}
}
I'm having difficulty using AutoMapper to convert Object from Nhibernate queries into my DTO in the following conf
Let's say I have 4 class.
class A
{
//some fields of built-in type
}
abstract class B //Some class derived this one, but this is not important here
{
//some fields of built-in type
public A refA { get; set; }
}
class C
{
//some fields of built-in type
public B refB { get; set; }
}
class D
{
//some fields of built-in type
public B refC { get; set; }
}
I use AutoMapper to convert it to my DTO, lets assume for simplicity here that the DTO is an exact copy of these class.
I want to send this through the wire, so before serializing, I ask AutoMapper to convert it in the DTO corresponding to the D-Class.
If I make these Object and configure the field my-self, when I call
Mapper.Map<T1,T2>(T1 source)
This is working. So my configuration AutoMap is working. More its also working with
Mapper.Map<IList<T1>,List<T2>
Very well.
Now I make these object, I put them in a Database and call a request to my SQL DB with Nhibernate to retrieve an IList (List of class D).
If I now try to convert it in DTO, it doesnt work anymore.
I trace the code in AutoMap, it maps correctly all the built-in type field in class D and then it comes to the refC and here it crash somewhere.
I know about lazy-loading and the fact that Nhibernate just gimme a proxy of my ref to class C but I dont see how to solve this.
Just so you know the NHibernateUtil.IsInitialized(refC) is true
Many Thanks
You will have to unproxy your entities before passing it to automapper. This is basically the same issue as if you would run a Json serialization.
You can use
Session.GetSessionImplementation().PersistenceContext.Unproxy();
to unproxy something.
Or you disable lazy loading.
Or you do not use automapper and instead use standard transformations... e.g.
.Query().Select(p => new SomeDto(){ PropA = p.PropA, ...});
You can also use another standard way:
resultSet = session.CreateCriteria(typeof(DataObject))
.Add(query criteria, etc.)
.SetResultTransformer(Transformers.AliasToBean<DTOObject>())
.List<IDTOObject>()
Basically you don't have to iterate all of the props. It is enough to be the same all class props between your DTO and data object.
I have a file Unit.cs
public class Unit
{
public UnitType UnitTypeState {get;set;}
}
public enum UnitType
{
Folder = 0,
Teststeps = 1,
}
When I put the enum definition into another class like UnitDTO I got this exception:
The property 'UnitTypeState' is not a declared property on type 'Unit'. Verify that the property has not been explicitly excluded from the model by using the Ignore method or NotMappedAttribute data annotation. Make sure that it is a valid primitive property.
Well thats not truee hehe the property UnitTypeState is a declared property in the Unit class class.
How can I fix that without moving the enum back to the Unit class?
UPDATE
I have still done some research about the bug:
"The context cannot be used while the model is being created."
The odd thing is I get this exception on a entity which is the parent of the entity with the UnitTyeState property ?!
using (var context = new ITMS.DataAccess.ITMSContext())
{
return context.Templates.ToList();
}
so it seems the template entity is created then this exception is thrown? Or behaves EF like this: At the first DB access at all every entities or the whole model is created?
Nested types are currently not supported by EF - applies to both StructuralType (i.e. entity and complex types) and enum types.
Adding a link to the EF work item that is exactly about this issue: http://entityframework.codeplex.com/workitem/119
Try using the following, Perhaps the enum just needs to derive from a primitive to work?
public enum UnitType : int
{
Folder = 0,
Teststeps = 1
}