Entity Framework Core v3 : Eliminating repeating data - c#

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);

Related

EF Core Include a view

I have the following relationships:
public class File
{
public string Path { get; set; }
}
public class Company
{
public string Name { get; set; }
}
public class Account
{
public int CompanyId { get; set; }
public Company Company { get; set; }
public int FileId { get; set; }
public File Avatar { get; set; }
}
public class Subject
{
public int AttachmentId { get; set; }
public File Attachment { get; set; }
}
public class Collaboration
{
public int SenderId { get; set; }
public Account Sender { get; set; }
public int ReceiverId { get; set; }
public Account Receiver { get; set; }
public int SubjectId { get; set; }
public Subject Subject { get; set; }
}
And I end up with this query
_dataContext
.Collaborations
.AsNoTracking()
.Include(x => x.Sender)
.ThenInclude(x => x.Company)
.Include(x => x.Sender)
.ThenInclude(x => x.Avatar)
.Include(x => x.Receiver)
.ThenInclude(x => x.Company)
.Include(x => x.Receiver)
.ThenInclude(x => x.Avatar)
.Include(x => x.Subject)
.ThenInclude(x => x.Attachment);
I'd like to know if it is possible to replace some of the Include / ThenInclude by a view using EF Core.
And if possible use it as
.Include(x => x.SenderAndCompanyInfo)
First create a sql view;
create view SenderAndCompany as
select s.Id,s.Name, s.SurName,c.CompanyName
from Sender s inner join Company c on c.Id = s.CompanyId
After creating sql view create model for it
public class SenderAndCompany
{
public int Id { get; set; }
public string Name { get; set; }
public string SurName { get; set; }
public string CompanyName { get; set; }
}
//Add to context
public DbSet<SenderAndCompany> SenderAndCompany { get; set; }
//map entity to view within the DbContext.OnModelCreating method
modelBuilder
.Entity<SenderAndCompany>()
.ToView(nameof(SenderAndCompany))
.HasKey(t => t.Id);
//Finally
_dataContext
.Collaborations
.AsNoTracking()
.Include(x => x.Sender)
.ThenInclude(x => x.SenderAndCompany)
.Include(x => x.Receiver)
.ThenInclude(x => x.Avatar)
.Include(x => x.Subject)
.ThenInclude(x => x.Attachment);

AutoMapper, the reverse map not working for embedded objects?

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:

How do I map Objects in this scenario using c# AutoMapper

This is the Source Object I want to map
public class Post
{
public string PostId { get; set; }
public string PostTitle { get; set; }
public virtual List<Comment> Comments { get; set; }
}
This destination object i want to map the source to
public class PostResponse
{
public int PostId { get; set; }
public string PostTitle { get; set; }
public IEnumerable<CommentObj> Comments { get; set; }
}
This is the Controller throwing the error
AutoMapper.AutoMapperMappingException: Error mapping types.
[HttpGet(ApiRoutes.Posts.GetAll)]
public async Task<IActionResult> GetAll()
{
var posts = await _postServices.GetPostsAsync();
return Ok(_mapper.Map<List<PostResponse>>(posts));
}
This is the Service
public async Task<List<Post>> GetPostsAsync()
{
var queryable = _dataContext.Posts.AsQueryable();
var psts = await queryable.Include(x => x.Comments).ToListAsync();
return psts;
}
This is the Mapping Profile
public DomainResponseProfile()
{
CreateMap<Post, PostResponse>().
ForMember(dest => dest.Comments, opt => opt.MapFrom(src => src.Comments.Select(x => new CommentResponse
{ PostId = x.PostId, DateCommented = x.DateCommented })));
}
This is the Domain Comment Object
public class Comment
{
public int CommentId { get; set; }
public int PostId { get; set; }
}
This is the Response Comment Object
public class CommentResponse
{
public int CommentId { get; set; }
public List<CommentObj> Comments { get; set; }
}
I just found out what I did wrong.
wrong
CreateMap<Post, PostResponse>().
ForMember(dest => dest.Comments, opt => opt.MapFrom(src => src.Comments.Select(x => new CommentResponse
{ PostId = x.PostId, DateCommented = x.DateCommented })));
right
CreateMap<Post, PostResponse>().
ForMember(dest => dest.Comments, opt => opt.MapFrom(src =>
src.Comments));

EF Working With One To Many Models With Composite Keys

I'm trying to learn .Net Core 2.1 and testing a little project with already existing database. We have 3 tables (Template, TemplateDesc, TemplateParameter) with one of them has one-to-many relationship. When I get one Template with controller, it returns null for TemplateDescriptions and ParameterValues. Also if I try to delete Template, it returns FK exception. Can someone point the problem with the below codes?
Note : I use Swagger extension to test codes.
public class Template
{
public decimal CompanyCode { get; set; }
public string TemplateCode { get; set; }
public List<TemplateDesc> TemplateDescriptions { get; set; }
public DateTime TemplateDate { get; set; }
public string RuleCode { get; set; }
public string SourceTypeCode { get; set; }
public string Description { get; set; }
public bool IsBlocked { get; set; }
public string CreatedUserName { get; set; }
public DateTime CreatedDate { get; set; }
public List<TemplateParameter> ParameterValues { get; set; }
}
public class TemplateDesc
{
public decimal CompanyCode { get; set; }
public string TemplateCode { get; set; }
public string LangCode { get; set; }
public string TemplateDescription { get; set; }
}
public class TemplateParameter
{
public decimal CompanyCode { get; set; }
public string TemplateCode { get; set; }
public string TemplateRuleCode { get; set; }
public string ParameterName { get; set; }
public string ParameterValue { get; set; }
}
modelBuilder.Entity<Template>(entity =>
{
entity.HasKey(e => new { e.CompanyCode, e.TemplateCode });
entity.HasMany(e => e.TemplateDescriptions).WithOne(e => e.Template).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode });
entity.HasMany(e => e.ParameterValues).WithOne(e => e.Template).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode });
}
modelBuilder.Entity<TemplateDesc>(entity =>
{
entity.HasKey(e => new { e.CompanyCode, e.TemplateCode, e.LangCode });
entity.HasOne(e => e.Template).WithMany(e => e.TemplateDescriptions).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode }).OnDelete(DeleteBehavior.Cascade);
}
modelBuilder.Entity<TemplateParameter>(entity =>
{
entity.HasKey(e => new { e.CompanyCode, e.TemplateCode, e.TemplateRuleCode, e.ParameterName});
entity.HasOne(e => e.Template).WithMany(e => e.ParameterValues).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode}).OnDelete(DeleteBehavior.Cascade);
}
[HttpGet]
public ActionResult<Template> GetWithKey([FromQuery] decimal companyCode, [FromQuery] string templateCode)
{
try
{
var template = this.mRepository.Find(e => e.CompanyCode == companyCode && e.TemplateCode.AreEqual(templateCode)).FirstOrDefault();
if (template == null)
return new JsonResult(new ApiResponse<Template>(ResponseType.Exception, null));
return new JsonResult(new ApiResponse<Template>(ResponseType.Success, template));
}
catch
{
throw;
}
}
[HttpDelete]
public ActionResult DeleteWithKey([FromQuery] decimal companyCode, [FromQuery] string templateCode)
{
if (this.mRepository.Find(e => e.CompanyCode == companyCode && e.TemplateCode.AreEqual(templateCode)).Count() < 1)
return new JsonResult(new ApiResponse<string>(ResponseType.NotFound, templateCode));
this.mRepository.Delete(companyCode, templateCode);
return new JsonResult(new ApiResponse<Template>(ResponseType.Success, null));
}
You have to either use lazy loading, or use Include construct:
db.Templates
.Include(x => x.TemplateDesc)
.Include(x => x.TemplateParameter)
.FirstOrDefault(...)
the includes can be put in extension method:
public IQueryable<Template> BuildTemplate(this DbSet<Template> set)
{
return set.Include(x => x.TemplateDesc)
.Include(x => x.TemplateParameter);
}
Then you can use
dbContext.Templates.BuildTemplate.FirstOrdefault(x => x.TemplateDescriptions.Any(td => td.TemplateCode == "xyz"));

EF6 fluent one-to-one stackoverflow

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...

Categories