I am trying to AutoMapper to EF models which are nested inside nested.
For Example in below code categorySrc, languageSrc, abstractSrc..etc and categoryDest, languageDest, abstractDest ..etc classes are same.
Now I am trying to Map categorySrc to categoryDest, So I made like below, if throwing an error
Is something I am doing wrong here?
var categoryData = abstractContext.GetCategoryByCatId(catId);
Mapper.CreateMap<Models.categoryDest, categorySource>();
Mapper.CreateMap<languageDest, Models.languageSource>();
Mapper.CreateMap<#abstractDest, Models.#abstractSrc>();
Mapper.CreateMap<abstract_categoryDest, Models.abstract_categorySrc>();
Mapper.CreateMap<questionDest, Models.questionSrc>();
Mapper.CreateMap ... //For other objects
Mapper.CreateMap ...//For other objects
Mapper.AssertConfigurationIsValid(); //Error occurring here
var category = Mapper.Map<category,Models.category>(categoryData);
Classes:
public partial class categoryDest
{
public int category_id { get; set; }
public int language_id { get; set; }
public virtual languageDest language { get; set; }
}
public partial class languageDest
{
public language()
{
this.abstracts = new HashSet<#abstractDest>();
this.abstract_category = new HashSet<abstract_categoryDest>();
this.categories = new HashSet<categoryDest>();
this.questions = new HashSet<questionDest>();
}
public int language_id { get; set; }
public string language_name { get; set; }
public string language_locale_code { get; set; }
public virtual ICollection<#abstractDest> abstracts { get; set; }
public virtual ICollection<abstract_categoryDest> abstract_category { get; set; }
public virtual ICollection<categoryDest> categories { get; set; }
public virtual ICollection<questionDest> questions { get; set; }
}
public partial class #abstractDest
{
public #abstract()
{
this.abstract_category = new HashSet<abstract_categoryDest>();
this.abstract_fields = new HashSet<abstract_fieldsDest>();
this.abstract_image = new HashSet<abstract_imageDest>();
this.people = new HashSet<person>();
}
public int abstract_id { get; set; }
public int language_id { get; set; }
public string abstract_name { get; set; }
public virtual ICollection<abstract_categoryDest> abstract_category { get; set; }
public virtual ICollection<abstract_fieldsDest> abstract_fields { get; set; }
public virtual ICollection<abstract_imageDest> abstract_image { get; set; }
public virtual languageDest language { get; set; }
public virtual ICollection<personDest> people { get; set; }
}
How to do this complex mapping?
Related
Hello I have a problem is that I cannot edit my model using a viewmodel and I tried to integrate the automapping but it did not work because in my viewmodel I have models at the Palce of properties I would like to know is if there is another simpler solution to make it work
error : System.InvalidOperationException : 'The instance of entity type 'SeDevisTest' cannot be tracked because another instance with the same key value for {'DevisId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
thank you
this is my Controller
public ActionResult edit(ViewModelEtudes viewModelEtudes)
{
ViewModelEtudes Etudes = new ViewModelEtudes();
serviceEtudesEnCours.remplirDrowdownliste(demId);
var resultDevis= _context.SeDevisTest.FirstOrDefault(item => item.DevisFkDemNum == demId);
if (resultDevis != null)
{
_context.Entry(viewModelEtudes.SeDevisTest).State = EntityState.Modified;
_context.SaveChanges();
}
return View(Etudes);
}
this is my view model it contains the entity that I will change se_devis
public class ViewModelEtudes
{
public SeDevisTest SeDevisTest { get; set; }
public SeDemande seDemandes { get; set; }
public SeInformationRecrutement InformationRecrutement { get; set; }
public SeControleProduit controleProduit { get; set; }
public SeQuestionnaire questionnaire { get; set; }
public SePersonnelSyres SePersonnelSyres { get; set; }
public SeTypeProduit SeTypeProduit { get; set; }
public List<SeCritereTest> SeCritereTest { get; set; }
public SePartenir sePartenirs { get; set; }
public SeTraitementDemande seTraitementDemandes { get; set; }
public SeInformationClient SeInformationClient { get; set; }
public SeClient SeInclient { get; set; }
public SeAssistantClient assitantclient { get; set; }
public SeReceptionProduit receptionProduit { get; set; }
public SePrestation prestation { get; set; }
public SeRapport seRapport { get; set; }
public SeResultat seResultat { get; set; }
public SeDemandeTypeProduit demandeTypeProduit { get; set; }
}
this is my Entity SE_DEVIS_TEST
public SeDevisTest()
{
Correspondance = new HashSet<Correspondance>();
SeCorrecponsance = new HashSet<SeCorrecponsance>();
SeFacture = new HashSet<SeFacture>();
SePlainte = new HashSet<SePlainte>();
SeQuestionnaire = new HashSet<SeQuestionnaire>();
SeRapport = new HashSet<SeRapport>();
}
public int DevisId { get; set; }
public DateTime? DevisDateCreation { get; set; }
public DateTime? DevisDateEnvoi { get; set; }
public bool? DevisAnnulation { get; set; }
public DateTime? DevisDateAnnulation { get; set; }
public int? DevisMotifAnnulationDesc { get; set; }
public bool? DevisConserverFacturation { get; set; }
public bool? DevisSigneReçu { get; set; }
public DateTime? DevisDateReception { get; set; }
public bool? DevisAttestationReçu { get; set; }
public DateTime? DevisDateReceptionAttestation { get; set; }
public string DevisConditionParticuliere { get; set; }
public int? DevisFkDemNum { get; set; }
public int? DevisFkSatisfaClientId { get; set; }
public int? DevisDiffcultéEstimé { get; set; }
public string DevisSy { get; set; }
public int? DevisNbRapport { get; set; }
public virtual SeQualiDifficulte DevisDiffcultéEstiméNavigation { get; set; }
public virtual SeTraitementDemande DevisFkDemNumNavigation { get; set; }
public virtual SeSatisfactionClient DevisFkSatisfaClient { get; set; }
public virtual SeColisage SeColisage { get; set; }
public virtual SeGestionBase SeGestionBase { get; set; }
public virtual SeInformationRecrutement SeInformationRecrutement { get; set; }
public virtual SeLettre SeLettre { get; set; }
public virtual SeOrganistationRecrutement SeOrganistationRecrutement { get; set; }
public virtual ICollection<Correspondance> Correspondance { get; set; }
public virtual ICollection<SeCorrecponsance> SeCorrecponsance { get; set; }
public virtual ICollection<SeFacture> SeFacture { get; set; }
public virtual ICollection<SePlainte> SePlainte { get; set; }
public virtual ICollection<SeQuestionnaire> SeQuestionnaire { get; set; }
public virtual ICollection<SeRapport> SeRapport { get; set; }
}
I currently working with .net core 2.1 and try to use automapper for nested objects to convert model to dto and dto to model. When every field is mapped correctly issue appears with relationship mapping.
Models
public class DropdownValue
{
public int Id { get; set; }
public string Value { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; }
}
public class Property
{
public int Id { get; set; }
public string Title { get; set; }
public ValueTypes ValueType { get; set; }
public InputTypes InputType { get; set; }
public List<DropdownValue> DropdownValues { get; set; }
}
Dtos
public class DropdownValueDto
{
public int Id { get; set; }
public string Value { get; set; }
public PropertyDto Property { get; set; }
}
public class PropertyDto
{
public int Id { get; set; }
public string Title { get; set; }
public InputTypes InputType { get; set; }
public ValueTypes ValueType { get; set; }
}
Mapper
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Property, PropertyDto>();
CreateMap<DropdownValue, DropdownValueDto>();
}
}
Usage in handler
_mapper.Map<List<Models.DropdownValue>, List<DropdownValueDto>>(dropdownValues)
I always use automapper mapping tool in .net 4x framework projects but when i develop .net core projects, i always use and recommend mapster mapping tool. It is pretty fast and simple ! Benchmark Results It also solves your problem. You can check the example usage where is below.
First create a mapper class.
public static class Mapper
{
public static void CreateMap()
{
TypeAdapterConfig<Property, PropertyDto>
.NewConfig();
TypeAdapterConfig<DropdownValue, DropdownValueDto>
.NewConfig();
}
}
Initialize in startup
public Startup(IHostingEnvironment env)
{
// other stuffs
// Mapping
Mapper.CreateMap();
}
Usage
dropdownValues.Adapt<List<Models.DropdownValue>, List<DropdownValueDto>>()
//Models
public class DropdownValue
{
public int Id { get; set; }
public string Value { get; set; }
public int PropertyId { get; set; }
public Property Property { get; set; } = new Property();
}
public class Property
{
public int Id { get; set; }
public string Title { get; set; }
public ValueTypes ValueType { get; set; } = new ValueTypes();
public InputTypes InputType { get; set; } = new InputTypes();
public List<DropdownValue> DropdownValues { get; set; } = new List<DropdownValue>();
}
//Dtos
public class DropdownValueDto
{
public int Id { get; set; }
public string Value { get; set; }
public PropertyDto Property { get; set; } = new PropertyDto();
}
public class PropertyDto
{
public int Id { get; set; }
public string Title { get; set; }
public InputTypes InputType { get; set; } = new InputTypes();
public ValueTypes ValueType { get; set; } = new ValueTypes();
}
I have a model classes defined as
public partial class RoadSegCond
{
public int ThanaID { get; set; }
public short RoadID { get; set; }
public int FromChain { get; set; }
public virtual SurfaceType SurfaceType { get; set; }
}
public partial class SurfaceType
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class SegmentWiseConditionViewModel
{
public int ThanaID { get; set; }
public short RoadID { get; set; }
public int FromChain { get; set; }
public string surfaceType { get; set; }
}
In my controller I want to send the information to a View model but it shows the
Error The specified type member 'SurfaceType' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
My controller is
public ActionResult Read([DataSourceRequest]DataSourceRequest request)
{
var model = from r in new RSDMSEntities().RoadSegConds
select new SegmentWiseConditionViewModel
{
RoadID = r.RoadID,
ThanaID = r.ThanaID,
FromChain = r.FromChain,
SurfaceType = r.SurfaceType.Name,
};
DataSourceResult result = model.ToDataSourceResult(request);
return Json(result);
}
the viewmodel
public class SegmentWiseConditionViewModel
{
public int ThanaID { get; set; }
public short RoadID { get; set; }
public int FromChain { get; set; }
public string surfaceType { get; set; }
}
I'm trying to use EF to get data from my database. I have a table Interventions that has a Client associated with it like this:
public partial class Client
{
public Client()
{
this.Interventions = new List<Intervention>();
}
public int client_id { get; set; }
public string full_name { get; set; }
public string cgroup { get; set; }
public string nation { get; set; }
public virtual ICollection<Intervention> Interventions { get; set; }
}
public partial class Intervention
{
public int intervention_id { get; set; }
public int technician_id { get; set; }
public int client_id { get; set; }
public string type { get; set; }
public int done { get; set; }
public int year { get; set; }
public int month { get; set; }
public int week { get; set; }
public Nullable<int> avg_response_time { get; set; }
public int number_of_equip { get; set; }
public virtual Client Client { get; set; }
public virtual Technician Technician { get; set; }
}
I can get a list of interventions by doing this:
public object Any(GetInterventions request)
{
List<Intervention> dbItems;
using (var context = new operationsContext())
{
context.Configuration.LazyLoadingEnabled = false;
dbItems = context.Interventions.ToList();
return new GetInterventionsResponse{
interventions = dbItems
};
}
}
Although, when I try to retrieve the client associated with each intervention
dbItems = context.Interventions.Include("Client").ToList();
by including a Client navigation property I get a Visual Studio a stackOverflowException.
Am I doing anything wrong using EF or is just a question of general bad programming?
thanks in advance
The problem was solved by introducing decorations of [DataContract] and [DataMember] on the classes and fields that I wanted to serialize on the JSON response. Just like the example below:
using System.Runtime.Serialization;
namespace OperationsAPI.Models
{
[DataContract]
public partial class Intervention
{
public int intervention_id { get; set; }
public int technician_id { get; set; }
public int client_id { get; set; }
public string type { get; set; }
public int done { get; set; }
public int year { get; set; }
[DataMember]
public int month { get; set; }
[DataMember]
public int week { get; set; }
[DataMember]
public Nullable<int> avg_response_time { get; set; }
public int number_of_equip { get; set; }
[DataMember]
public virtual Client Client { get; set; }
public virtual Technician Technician { get; set; }
}
}
I have a database with 3 tables:
Subjects
Members
Topics
Then I added the connection string to web.config and created an EF with the following classes:
namespace MySite.Models
{
public class MySiteDBModel : DbContext
{
public DbSet<Topic> Topics { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Member> Members { get; set; }
public DbSet<TopicDataModel> TopicDataModel { get; set; }
protected override void OnModelCreating(DbModelBuilder mb)
{
mb.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class Topic
{
[Key]
public int TopicID { get; set; }
public int SubID { get; set; }
public int MemberID { get; set; }
public string TDate { get; set; }
public string Title { get; set; }
public string FileName { get; set; }
public int Displays { get; set; }
public string Description { get; set; }
public virtual Subject Subject { get; set; }
public virtual Member Member { get; set; }
public virtual ICollection<TopicView> TopicView { get; set; }
}
public class Subject
{
[Key]
public int SubID { get; set; }
public string SubName { get; set; }
public virtual ICollection<Topic> Topic { get; set; }
}
public class Member
{
[Key]
public int MemberID { get; set; }
public string FLName { get; set; }
public string Email { get; set; }
public string Pwd { get; set; }
public string About { get; set; }
public string Photo { get; set; }
public virtual ICollection<Topic> Topic { get; set; }
}
public class TopicDataModel
{
[Key]
public int TopicID { get; set; }
public string SubName { get; set; }
public string FLName { get; set; }
public string TDate { get; set; }
public string Title { get; set; }
public int Displays { get; set; }
public string Description { get; set; }
}
}
Now when I am trying to query the database with the this code:
public ActionResult Index()
{
var topics = from t in db.Topics
join s in db.Subjects on t.SubID equals s.SubID
join m in db.Members on t.MemberID equals m.MemberID
select new TopicDataModel()
{
TopicID = t.TopicID,
SubName = s.SubName,
FLName = m.FLName,
TDate = t.TDate,
Title = t.Title,
Displays = t.Displays,
Description = t.Description
};
return View(topics.ToList());
}
I got this Error:
The model backing the 'MySiteDBModel' context has changed since the
database was created. Either manually delete/update the database, or
call Database.SetInitializer with an IDatabaseInitializer instance.
For example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
Please help me!!!!!!
You need to set some controls on how EF is handling changes to your data model. Julie Lerman has a good blog post on Turning Off Code First Database Initialization Completely.
Also, here is a good overview - Inside Code First Database Initialization