I have a class Affaire, containing Secteurs, containing associated Emplacements, and corresponding DTO objects to transform. I use AutoMapper for that.
public class Affaire
{
public string Nom { get; set; }
public class Emplacement
{
public int AffaireId { get; set; }
public Affaire Affaire { get; set; }
public class EmplacementDTO
{
public int AffaireId { get; set; }
public string AffaireNom { get; set; }
The Emplacements are grouped in Secteur, having as well its Affaire
public class Secteur
{
public int AffaireId { get; set; }
public Affaire Affaire { get; set; }
public IList<Emplacement> Emplacements { get; set; } = new List<Emplacement>();
When I map from Emplacement to a EmplacementDTO I don't want to include Affaire, only AffaireId:
CreateMap<Emplacement, EmplacementDTO>()
.ForMember(dto => dto.AffaireId, o => o.MapFrom(dto => dto.Affaire.Id))
.ForMember(dto => dto.AffaireNom, o => o.MapFrom(dto => dto.Affaire.Nom))
.ReverseMap()
.ForPath(bo => bo.Affaire, o => o.MapFrom(dto => (Affaire)null)); // <<<< HERE
This configuration does not seem to work when Emplacement is embedded in a container SecteurDTO, however, for the container itself, the configurartion seem to work (its Affaire is set to null):
CreateMap<Secteur, SecteurDTO>()
.ForMember(dto => dto.AffaireId, o => o.MapFrom(dto => dto.Affaire.Id))
.ForMember(dto => dto.AffaireNom, o => o.MapFrom(dto => dto.Affaire.Nom))
.ReverseMap()
.ForPath(bo => bo.Affaire, o => o.MapFrom(dto => (Affaire)null))
related problem here
Here is the working demo in my project:
Model:
public class Affaire
{
public int Id { get; set; }
public string Nom { get; set; }
public IList<Emplacement> Emplacements { get; set; } = new List<Emplacement>();
}
public class Emplacement
{
public int AffaireId { get; set; }
public Affaire Affaire { get; set; }
}
public class Secteur
{
public int AffaireId { get; set; }
public Affaire Affaire { get; set; }
public IList<Emplacement> Emplacements { get; set; } = new List<Emplacement>();
}
DTO:
public class EmplacementDTO
{
public int AffaireId { get; set; }
public string AffaireNom { get; set; }
public Affaire Affaire { get; set; }
}
public class SecteurDTO
{
public int AffaireId { get; set; }
public string AffaireNom { get; set; }
public Affaire Affaire { get; set; }
public IList<EmplacementDTO> Emplacements { get; set; }
}
Profile:
public class YourProfile : Profile
{
public YourProfile()
{
CreateMap<Emplacement, EmplacementDTO>()
.ForMember(dto => dto.AffaireId, o => o.MapFrom(dto => dto.Affaire.Id))
.ForMember(dto => dto.AffaireNom, o => o.MapFrom(dto => dto.Affaire.Nom))
.ReverseMap()
.ForPath(bo => bo.Affaire, o => o.MapFrom(dto => (Affaire)null));
CreateMap<Secteur, SecteurDTO>()
.ForMember(dto => dto.AffaireId, o => o.MapFrom(dto => dto.Affaire.Id))
.ForMember(dto => dto.AffaireNom, o => o.MapFrom(dto => dto.Affaire.Nom))
.ReverseMap()
.ForPath(bo => bo.Affaire, o => o.MapFrom(dto => (Affaire)null));
}
}
Backend testing code:
public List<EmployeeModel> Index(List<SecteurDTO> dto)
{
dto = new List<SecteurDTO>()
{
new SecteurDTO(){
AffaireId=1,
AffaireNom="aaa",
Emplacements = new List<EmplacementDTO>()
{
new EmplacementDTO(){AffaireId=1,Affaire=new Affaire(){Id=1,Nom="aa"}}
},
Affaire=new Affaire(){
Id=1,
Nom="aaa",
Emplacements=new List<Emplacement>()
{
new Emplacement(){AffaireId=1,Affaire=new Affaire(){Id=1,Nom="aa"}}
}
}
}
};
var bo= new List<Secteur>() { };
var mapper = _mapper.Map(dto, bo);
//...
}
Result:
Related
I am using Entity Framework Core v3. I am currently trying to retrieve data from tables that contain a one-to-many relationship.
The tables here are PersonNote and PersonNoteAttachment.
One PersonNote can have many PersonNoteAttachments. Data is getting currently repeated. So if you see the result section it has Name appearing twice. This is just an example. I am not sure if I need to change the query or change the model structure etc. Could somebody help
PersonNote
Id Name
-------------
113 TestNote
PersonNoteAttachment
Id PersonNoteId Note
---------------------------------
101 113 Attachment1
102 113 Attachment2
Result
TestNote Attachment1
TestNote Attachment2
What I am looking at is
TestNote Attachment1
Attachment2
Query
public IQueryable<PersonNote> GetPersonNotes(int personId)
{
var personNotes = _context.PersonNotes
.Include(x => x.Person)
.Include(x => x.Author)
.Include(x => x.PersonNoteAttachment)
.Where(p => p.PersonId == personId)
.OrderByDescending(d => d.Created);
return personNotes;
}
Model
namespace Organisation.Models.DataModels
{
[Table(nameof(PersonNote), Schema = "common")]
public class PersonNote
{
public int Id { get; set; }
public int PersonId { get; set; }
[ForeignKey("PersonId")]
public Person Person { get; set; }
public string Note { get; set; }
public int AuthorId { get; set; }
public PersonNoteAttachment PersonNoteAttachment { get; set; }
[ForeignKey("AuthorId")]
public Person Author { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordStartDateTime { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordEndDateTime { get; set; }
}
public class PersonNoteAttachment
{
public int Id { get; set; }
public int PersonNoteId { get; set; }
[ForeignKey("PersonNoteId")]
public PersonNote PersonNote { get; set; }
public string Alias { get; set; }
public string FileName { get; set; }
public string MimeType { get; set; }
public int Deleted { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordStartDateTime { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordEndDateTime { get; set; }
}
Mapping
CreateMap<Organisation.Models.DataModels.PersonNote, Organisation.Models.User.PersonNote>()
.ForMember(t => t.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(t => t.PersonId, opt => opt.MapFrom(s => s.PersonId))
.ForMember(t => t.AuthorName, opt => opt.MapFrom(s => s.Author.FirstName + " " + s.Author.LastName))
.ForMember(t => t.FileName, opt => opt.MapFrom(s => s.PersonNoteAttachment.FileName))
.ForMember(t => t.MimeType, opt => opt.MapFrom(s => s.PersonNoteAttachment.MimeType))
.ForMember(t => t.Alias, opt => opt.MapFrom(s => s.PersonNoteAttachment.Alias))
.ForMember(t => t.Note, opt => opt.MapFrom(s => s.Note))
.ForMember(t => t.AuthorId, opt => opt.MapFrom(s => s.AuthorId))
.ForMember(t => t.CreatedBy, opt => opt.MapFrom(s => s.CreatedBy))
.ForMember(t => t.Created, opt => opt.MapFrom(s => s.Created));
If you notice PersonNoteAttachment is not an array. If I make it an array, then the following changes would need to be done:
public PersonNoteAttachment[] PersonNoteAttachment { get; set; }
and in the mapping to avoid compile errors
.ForMember(t => t.FileName, opt => opt.MapFrom(s => s.PersonNoteAttachment[0].FileName))
API
[FunctionName(nameof(GetPersonNote))]
[UsedImplicitly]
public Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "person-note/{id}")] HttpRequest req,
int id) => _helper.HandleAsync(async () =>
{
// await _helper.ValidateRequestAsync(req, SecurityPolicies.ViewNotes);
var personNotes = await _organisationRepository.GetPersonNotes(id).ProjectTo<PersonNote>(_mapper.ConfigurationProvider).ToListAsync();
return new OkObjectResult(personNotes);
});
ViewModel
namespace Organisation.Models.User
{
[Table(nameof(PersonNote), Schema = "common")]
public class PersonNote
{
public int Id { get; set; }
public int PersonId { get; set; }
public string Note { get; set; }
public int AuthorId { get; set; }
public string Alias { get; set; }
public string FileName { get; set; }
public string MimeType { get; set; }
public string AuthorName { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
}
}
Solution 1 - But with internal exception
Unable to cast object of type 'System.Boolean' to type 'System.Int32'.
Tried the following , which is providing the desired results . The postman returns 200k. Although debugging the code throwing an internal exception.
Added
Datamodel
namespace Organisation.Models.DataModels
{
public class PersonNote
{
public IEnumerable<PersonNoteAttachment> PersonNoteAttachment { get; set; }
}
}
Viewmodel
namespace Organisation.Models.User
{
[Table(nameof(PersonNote), Schema = "common")]
public class PersonNote
{
public IEnumerable<string> Alias { get; set; }
public IEnumerable<string> FileName { get; set; }
public IEnumerable<string> MimeType { get; set; }
}
}
Mapping
.ForMember(t => t.FileName, opt => opt.MapFrom(s => s.PersonNoteAttachment.Select(x=> x.FileName)))
.ForMember(t => t.MimeType, opt => opt.MapFrom(s => s.PersonNoteAttachment.Select(x => x.MimeType)))
.ForMember(t => t.Alias, opt => opt.MapFrom(s => s.PersonNoteAttachment.Select(x => x.Alias)))
Abduls solution
API
[FunctionName(nameof(GetPersonNote))]
[UsedImplicitly]
public Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "person-note/{id}")] HttpRequest req,
int id) => _helper.HandleAsync(async () =>
{
await _helper.ValidateRequestAsync(req, SecurityPolicies.ViewNotes);
var personNotes = _organisationRepository.GetPersonNotes(id);
//IEnumerable<PersonNote> personNotes = groupedNotes.Select(Profiles.GenistarUserProfile.MapGroupToPersonNote);
return new OkObjectResult(personNotes.ToList());
});
Repository
public IQueryable<Genistar.Organisation.Models.User.PersonNote> GetPersonNotes(int personId)
{
var personNotes = _context.PersonNotes
.Include(x => x.Person)
.Include(x => x.Author)
.Where(p => p.PersonId == personId).Select(x => new Genistar.Organisation.Models.User.PersonNote
{
//assign all properties
Attachments = _context.PersonNotesAttachments.Where(y => y.PersonNoteId == x.Id).Select(y => new Genistar.Organisation.Models.User.PersonNoteAttachment
{
FileName = y.FileName,
Alias = y.Alias,
MimeType = y.MimeType
}),
PersonId = x.PersonId,
AuthorName = x.Person.FirstName + " " + x.Person.LastName,
Note = x.Note,
Id = x.Id,
Created = x.Created
}).OrderByDescending(x=> x.Created).AsNoTracking();
return personNotes;
}
The following code will allow you to use a 3 layered architecture with your app, and try to reduce the coupling between your layers while keeping your existing structure.
To start, change your query:
public IQueryable<DataModel.PersonNote> GetPersonNotes(int personId)
{
var personNotes = _context.PersonNotes
.Include(x => x.Person)
.Include(x => x.Author)
.Where(p => p.PersonId == personId);
return personNotes;
}
And add another repo query:
public IQueryable<DataModel.PersonNoteAttachment> GetAttachments(int personNoteId)
{
var attachments = _context.PersonNotesAttachments.Where(x => x.Id == personNoteId);
return attachments ;
}
Use the following Models, PersonNote being your ViewModel:
namespace Organisation.Models.User
{
public class PersonNoteAttachment
{
public string Alias { get; set; }
public string FileName { get; set; }
public string MimeType { get; set; }
}
public class PersonNote
{
public int Id { get; set; }
public int PersonId { get; set; }
public string Note { get; set; }
public int AuthorId { get; set; }
public IEnumerable<PersonNoteAttachment> Attachments { get; set; }
public string AuthorName { get; set; }
public string CreatedBy { get; set; }
public DateTime Created { get; set; }
}
}
Now we create a new function in BL layer that will return your data for the ViewModel:
public IEnumerable<User.PersonNote> GetPersonNotesAndAttachments(int personID)
{
var personNotes = _organisationRepository.GetPersonNotes(id).Select(x =>
new User.PersonNote
{
//assign all properties
Attachments = _organisationRepository.GetAttachments(x.PersonNoteID).Select(y =>
new User.PersonNoteAttachment
{
FileName = y.FileName,
Alias = y.Alias,
MimeType = y.MimeType
}).AsEnumerable(),
PersonId = x.PersonId,
AuthorName = x.Person.FirstName + " " + x.Person.LastName,
Note = x.Note,
Id = x.Id,
Created = x.Created
});
return personNotes;
}
The IEnumerable<PersonNote> "What I am looking at is" can be accessed like this:
IEnumerable<User.PersonNote> personNotes = new BlClass().GetPersonNotesAndAttachments(id);
AutoMapper is not projecting query in EF when using ExplicitExpansion in a property that is defined in a base class. The following code shows the models:
/*********** Source Types ***********/
class EntityBase
{
public Guid? CreatedById { get; set; }
public Guid? ModifiedById { get; set; }
[ForeignKey("CreatedById")]
public User CreatedBy { get; set; }
[ForeignKey("ModifiedById")]
public User ModifiedBy { get; set; }
}
class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
class Script : EntityBase
{
[Key]
public Guid Id { get; set; }
public string Text { get; set; }
}
/*********** Destination Types ***********/
class EntityBaseModel
{
public Guid? CreatedById { get; set; }
public Guid? ModifiedById { get; set; }
public UserModel CreatedBy { get; set; }
public UserModel ModifiedBy { get; set; }
}
class UserModel
{
public Guid Id { get; set; }
public string Name { get; set; }
}
class ScriptModel : EntityBaseModel
{
public Guid Id { get; set; }
public string Text { get; set; }
public new UserModel ModifiedBy { get; set; } //notice the 'new' here? this will work
}
I'm using the following mapping configuration:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Script, ScriptModel>()
.MaxDepth(1)
.ForMember(d => d.ModifiedBy, o => o.ExplicitExpansion())
.ForMember(d => d.CreatedBy, o => o.ExplicitExpansion());
});
The following test will fail, but it shouldn't... it should fetch the CreatedBy property because I've explicitly said so:
/// <summary>
/// This will fail, but it shouldn't.
/// </summary>
[TestMethod]
public void Should_Map_CreatedBy()
{
using (var context = new MyContext())
{
var model = context.Scripts.Include("CreatedBy").ProjectTo<ScriptModel>(null, "CreatedBy").FirstOrDefault();
Assert.IsNotNull(model);
Assert.IsNotNull(model.CreatedBy);
}
}
I've also tried these configurations, but it doesn't work either
Mapper.Initialize(cfg =>
{
cfg.CreateMap<EntityBase, EntityBaseModel>();
cfg.CreateMap<User, UserModel>();
cfg.CreateMap<Script, ScriptModel>()
.MaxDepth(1)
.ForMember(d => d.ModifiedBy, o => o.ExplicitExpansion())
.ForMember(d => d.CreatedBy, o => o.ExplicitExpansion());
});
Mapper.Initialize(cfg =>
{
cfg.CreateMap<EntityBase, EntityBaseModel>();
cfg.CreateMap<User, UserModel>();
cfg.CreateMap<Script, ScriptModel>()
.IncludeBase<EntityBase, EntityBaseModel>()
.MaxDepth(1)
.ForMember(d => d.ModifiedBy, o => o.ExplicitExpansion())
.ForMember(d => d.CreatedBy, o => o.ExplicitExpansion());
});
Is there something wrong with my mapping configuration? Is that an automapper bug?
Here's the full repro: https://1drv.ms/u/s!AhH0QYI81F61gtIx0q27BZ05EM-xQA
cfg.CreateMap<User, UserModel>();
cfg.CreateMap<Script, ScriptModel>()
.ForMember(d => d.ModifiedBy, o => o.ExplicitExpansion())
.ForMember(d => d.CreatedBy, o => o.ExplicitExpansion());
var model = context.Scripts.ProjectTo<ScriptModel>(s=>s.CreatedBy).FirstOrDefault()
This works for me with the latest version.
I'm struggling to map 2 objects. Basically have Product which is my EF model, and I'm mapping this to ProductDto, which has FileDto.
I'd like to map Product.FileName to ProductDto.File.Internal name, how to do this?
Classes below.
public class Product : BaseEntity<long>
{
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Barcode { get; set; }
public int ShelfLife { get; set; }
public int Weight { get; set; }
public bool HasAllergens { get; set; }
[MaxLength(100)]
public string FileName { get; set; }
[ForeignKey("Id")]
public int CustomerId { get; set; }
public virtual ICollection<ProductIngredient> ProductIngredient { get; set; }
public virtual ICollection<Nutrition> Nutritions { get; set; }
public virtual ICollection<ProductComposition> Composition { get; set; }
public virtual IList<ProductionProcess> ProductionProcess { get; set; }
}
public class ProductDto
{
public long Id { get; set; }
public DateTime CretedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public string Name { get; set; }
public string Barcode { get; set; }
public int ShelfLife { get; set; }
public int Weight { get; set; }
public bool HasAllergens { get; set; }
public int CustomerId { get; set; }
public FileDto File { get; set; }
public IList<IngredientDto> Ingredients { get; set; }
public IList<NutritionDto> Nutritions { get; set; }
public IList<ProductCompositionDto> Composition { get; set; }
public IList<ProductionProcessDto> ProductionProcess { get; set; }
}
public class ProductionProcessDto
{
public string Key { get; set; }
public string Value { get; set; }
public FileDto File { get; set; }
}
public class NutritionDto
{
public string Key { get; set; }
public string Value { get; set; }
}
public class ProductCompositionDto
{
public string Key { get; set; }
public string Value { get; set; }
}
File Dto:
public class FileDto
{
public string Base64EncodedFile { get; set; }
public string OriginalName { get; set; }
public string InternalName { get; set; }
public string Type { get; set; }
}
Automapper so far:
//Product
CreateMap<Nutrition, NutritionDto>().ReverseMap();
CreateMap<ProductComposition, ProductCompositionDto>().ReverseMap();
CreateMap<ProductionProcessDto, ProductionProcess>()
.ForMember(dest => dest.FileInternalName, opt => opt.MapFrom(src => src.File.InternalName))
.ForMember(dest => dest.FileOriginalName, opt => opt.MapFrom(src => src.File.OriginalName))
.ReverseMap();
CreateMap<Product, ProductDto>()
.ForMember(d => d.File, o => o.MapFrom(s => Mapper.Map<Product, FileDto>(s)))
.ForMember(d => d.Nutritions, o => o.MapFrom(s => s.Nutritions))
.ForMember(d => d.Composition, o => o.MapFrom(s => s.Composition))
.ForMember(d => d.ProductionProcess, o => o.MapFrom(s => s.ProductionProcess))
.ForMember(d => d.Ingredients, o => o.MapFrom(s => s.ProductIngredient.Select(pi => pi.Ingredients)))
.ReverseMap();
CreateMap<ProductDto, Product>()
.ForMember(d => d.FileName, o => o.MapFrom(s => s.File.InternalName))
.ReverseMap();
I am able to map from ProductDto (on data post) to Product but not other way around, all help much appreciated
Thanks
This code solved my issue:
.ForMember(d => d.File, o => o.MapFrom(model => new FileDto { InternalName = model.FileName }))
Applied to:
CreateMap<Product, ProductDto>()
I have read a lot of posts and some helped me, but I still have a stackoverflow on a one-to-one relation (between Employe and Adresse) defined with Entity framework 6 fluent.
The error appears on AdresseDTO when I create a new instance of a ViewModel wich contains some DTOs.
My plain objects
public class Personne
{
public int id { get; set; }
public string civ { get; set; }
public string nom { get; set; }
public string prenom { get; set; }
public string email { get; set; }
public string tel1 { get; set; }
public string tel2 { get; set; }
public Boolean isFournisseur { get; set; }
public Boolean isClient { get; set; }
public Boolean isDeleted { get; set; }
public virtual Adresse adresse { get; set; }
public virtual Utilisateur utilisateur { get; set; }
public Personne()
{
}
}
public class Employe : Personne
{
public virtual TEmploye typeEmploye { get; set; }
public virtual List<AffectationService> affectationServices { get; set; }
public Employe()
{
}
}
public class AffectationService
{
public int id { get; set; }
public virtual Employe employe { get; set; }
public virtual Service service { get; set; }
public virtual Droit groupe { get; set; }
public Boolean isPrincipal { get; set; }
}
public class TEmploye
{
public int id { get; set; }
public string libe { get; set; }
public TEmploye()
{
}
}
public class Adresse
{
public int id { get; set; }
public string numRue { get; set; }
public string nomRue { get; set; }
public string codePostal { get; set; }
public string ville { get; set; }
public string pays { get; set; }
public virtual Personne personne { get; set; }
public Adresse()
{
}
}
My DTOs
public class PersonneDTO
{
public int id { get; set; }
public bool isDeleted { get; set; }
public string civ { get; set; }
public string nom { get; set; }
public string prenom { get; set; }
public string email { get; set; }
public string tel1 { get; set; }
public string tel2 { get; set; }
public AdresseDTO adresse { get; set; }
public UtilisateurDTO utilisateur { get; set; }
public PersonneDTO()
{
adresse = new AdresseDTO();
utilisateur = new UtilisateurDTO();
}
}
public class EmployeDTO : PersonneDTO
{
public virtual TEmployeDTO typeEmploye { get; set; }
public virtual List<AffectationServiceDTO> affectationServices { get; set; }
public EmployeDTO()
{
affectationServices = new List<AffectationServiceDTO>();
typeEmploye = new TEmployeDTO();
}
}
public class TEmployeDTO
{
public int id { get; set; }
public string libe { get; set; }
public TEmployeDTO()
{
}
}
public class AffectationServiceDTO
{
public int id { get; set; }
public virtual EmployeDTO employe { get; set; }
public virtual ServiceDTO service { get; set; }
public virtual DroitDTO groupe { get; set; }
public Boolean isPrincipal { get; set; }
public AffectationServiceDTO()
{
service = new ServiceDTO();
groupe = new DroitDTO();
employe = new EmployeDTO();
}
}
public class AdresseDTO
{
public int id { get; set; }
public string numRue { get; set; }
public string nomRue { get; set; }
public string codePostal { get; set; }
public string ville { get; set; }
public string pays { get; set; }
public AdresseDTO()
{
}
}
How I mapp my DTOs with the plain objects
//DomainToViewModel
CreateMap<Adresse, AdresseDTO>().MaxDepth(1);
CreateMap<Personne, PersonneDTO>().MaxDepth(1);
CreateMap<Employe, EmployeDTO>().MaxDepth(1);
CreateMap<AffectationService, AffectationServiceDTO>().MaxDepth(1);
CreateMap<TEmploye, TEmployeDTO>().MaxDepth(1);
//ViewModelToDomain
CreateMap<AdresseDTO, Adresse>().MaxDepth(1)
.ForMember(g => g.id, map => map.MapFrom(vm => vm.id))
.ForMember(g => g.codePostal, map => map.MapFrom(vm => vm.codePostal))
.ForMember(g => g.nomRue, map => map.MapFrom(vm => vm.nomRue))
.ForMember(g => g.numRue, map => map.MapFrom(vm => vm.numRue))
.ForMember(g => g.pays, map => map.MapFrom(vm => vm.pays))
.ForMember(g => g.ville, map => map.MapFrom(vm => vm.ville));
CreateMap<UtilisateurDTO, Utilisateur>().MaxDepth(1)
.ForMember(g => g.id, map => map.MapFrom(vm => vm.id))
.ForMember(g => g.dConnexion, map => map.MapFrom(vm => vm.dConnexion))
.ForMember(g => g.dCreation, map => map.MapFrom(vm => vm.dCreation))
.ForMember(g => g.isActive, map => map.MapFrom(vm => vm.isActive))
.ForMember(g => g.isDeleted, map => map.MapFrom(vm => vm.isDeleted))
.ForMember(g => g.login, map => map.MapFrom(vm => vm.login))
.ForMember(g => g.password, map => map.MapFrom(vm => vm.password))
.ForMember(g => g.personne, map => map.MapFrom(vm => vm.personne)).MaxDepth(1);
CreateMap<EmployeDTO, Employe>().MaxDepth(1)
.ForMember(g => g.id, map => map.MapFrom(vm => vm.id))
.ForMember(g => g.typeEmploye, map => map.MapFrom(vm => vm.typeEmploye))
.ForMember(g => g.affectationServices, map => map.MapFrom(vm => vm.affectationServices))
.ForMember(g => g.utilisateur, map => map.MapFrom(vm => vm.utilisateur)).MaxDepth(1)
.ForMember(g => g.adresse, map => map.MapFrom(vm => vm.adresse)).MaxDepth(1);
CreateMap<TEmployeDTO, TEmploye>().MaxDepth(1)
.ForMember(g => g.libe, map => map.MapFrom(vm => vm.libe));
CreateMap<AffectationServiceDTO, AffectationService>().MaxDepth(1)
.ForMember(g => g.id, map => map.MapFrom(vm => vm.id))
.ForMember(g => g.employe, map => map.MapFrom(vm => vm.employe)).MaxDepth(1)
.ForMember(g => g.groupe, map => map.MapFrom(vm => vm.groupe)).MaxDepth(1)
.ForMember(g => g.isPrincipal, map => map.MapFrom(vm => vm.isPrincipal))
.ForMember(g => g.service, map => map.MapFrom(vm => vm.service)).MaxDepth(1);
Mapping with EF6 fluent
public PersonneConfiguration()
{
ToTable("Personne");
HasKey<int>(a => a.id);
HasRequired<Adresse>(x => x.adresse);
HasOptional<Utilisateur>(x => x.utilisateur);
Property(a => a.civ).HasColumnType("varchar").HasMaxLength(3);
Property(a => a.nom).HasColumnType("varchar").HasMaxLength(80);
Property(a => a.prenom).HasColumnType("varchar").HasMaxLength(80);
Property(a => a.email).HasColumnType("varchar").HasMaxLength(150);
Property(a => a.tel1).HasColumnType("varchar").HasMaxLength(10);
Property(a => a.tel2).HasColumnType("varchar").HasMaxLength(10);
Property<bool>(a => a.isClient);
Property<bool>(a => a.isFournisseur);
Property<bool>(a => a.isDeleted);
}
public EmployeConfiguration()
{
ToTable("Employe");
HasKey<int>(a => a.id);
HasOptional<TEmploye>(x => x.typeEmploye);
Property<bool>(a => a.isDeleted);
}
public AdresseConfiguration()
{
ToTable("Adresse");
HasKey<int>(a => a.id);
Property(a => a.codePostal).HasColumnType("varchar").HasMaxLength(5);
Property(a => a.nomRue).HasColumnType("varchar").HasMaxLength(150);
Property(a => a.numRue).HasColumnType("varchar").HasMaxLength(10);
Property(a => a.ville).HasColumnType("varchar").HasMaxLength(80);
Property(a => a.pays).HasColumnType("varchar").HasMaxLength(80);
}
public AffectationServiceConfiguration()
{
ToTable("AffectationService");
HasKey<int>(a => a.id);
HasRequired<Employe>(x => x.employe).WithMany(x => x.affectationServices);
HasRequired<Service>(x => x.service);
HasRequired<Droit>(x => x.groupe);
Property<bool>(a => a.isPrincipal);
}
public TEmployeConfiguration()
{
ToTable("TEmploye");
HasKey<int>(a => a.id);
Property(a => a.libe).HasColumnType("varchar").HasMaxLength(100);
}
And the ViewModel taht causes the error
public class EditEmployeViewModel
{
public EmployeDTO personne { get; set; }
public EditEmployeViewModel()
{
personne = new EmployeDTO();
}
}
The stackoverflow occurs when a create a new EmployeDTO(). I tried to solve this by adding .MaxDepth(1) where it's possible, but it doesn't work...
Sorry guys, I know that is a long post, but I don't have any idea about my problem so I try to show you the most relevent part of my code.
Thank you for all, I'm brand new in EF6 so if you have any tips or good pratices to share it will be a pleasure.
thank you for your help.
I didnt' find a real solution so I removed the refererence Personne in my object Adresse to avoid the stackoverflow exception...
I'm looking for any how to or documentation about use of Embeddable with FluentNHibernate exactly with in the Hibernate. Does has any way to works with Embeddable in FluentNHibernate, if not has what's the best way to simulate this ?
Finally I found some solution. It's very simple like Embeddable of JPA/Hibernate.
Found here: https://github.com/jagregory/fluent-nhibernate/wiki/Fluent-mapping#components
Then I did.
public class Cliente {
public virtual long id { set; get; }
public virtual long codigo { set; get; }
public virtual String nome { set; get; }
public virtual String sexo { set; get; }
public virtual String cpf { set; get; }
public virtual String rg { set; get; }
public virtual DateTime dtNascimento { set; get; }
public virtual Endereco endereco { set; get; } //Embeddable
public Cliente() { }
}
public class Endereco {
public String endereco;
public String numero;
public String bairro;
public String complemento;
public String cidade;
public String cep;
public EstadosBrasil uf;
public Endereco() {
}
}
Mapping
public class ClienteMap : ClassMap<Cliente> {
public ClienteMap() {
Table("CLIENTE");
Id(c => c.id).GeneratedBy.Native();
Map(c => c.codigo);
Map(c => c.nome);
Map(c => c.sexo).Length(2);
Map(c => c.cpf);
Map(c => c.rg);
Map(c => c.dtNascimento).CustomType<DateTime>();
//embeddable
Component(c => c.endereco, e => {
e.Map(c => c.endereco);
e.Map(c => c.numero).CustomType<int>();
e.Map(c => c.bairro);
e.Map(c => c.complemento);
e.Map(c => c.cidade);
e.Map(c => c.cep);
e.Map(c => c.uf).CustomType<GenericEnumMapper<EstadosBrasil>>();
});
}
}