Automapper DTO to Entity Nested Mapping - entity-framework

I have entities:
public class Person
{
//properties
public virtual State State { get; set; }
}
public class State
{
//properties
public int StateId { get; set; }
public string StateName { get; set; }
public virtual Address Address{ get; set; }
}
public class Address
{
//properties
public int AddressId { get; set; }
public string City{ get; set; }
public int PostalCode { get; set; }
}
And i have a flatten DTO called PersonDetails
public class PersonDetails
{
//properties
public string City { get; set; }
public string StateName { get; set; }
public int PostalCode { get; set; }
}
When I do the mapping it works but it creates a new State and Adress for the Person entity.
How would I use AutoMapper to map from PersonDetails to PersonEntity?

Related

Insert/Add new entity with nested children entities to DB using Entity Framework Core

Here are Entities:
public class Entity
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
}
public class EntityBase : Entity
{
[ForeignKey("CreatedBy")]
public int CreatedById { get; set; }
public User CreatedBy { get; set; }
[ForeignKey("ModifiedBy")]
public int? ModifiedById { get; set; }
public User ModifiedBy { get; set; }
}
public class ProjectRequest : EntityBase
{
public string RequestTitle { get; set; }
public string RequestType { get; set; }
...
public virtual ICollection<Material> Materials { get; set; }
public virtual ICollection<Translation> Translations { get; set; }
}
public class Material : EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
...
public virtual ICollection<Translation> Translations { get; set; }
}
public class Translation:EntityBase
{
[ForeignKey("ProjectRequest")]
public int ProjectRequestId { get; set; }
public virtual ProjectRequest ProjectRequest { get; set; }
[ForeignKey("Material")]
public int MaterialId { get; set; }
public virtual Material Material { get; set; }
public string ProductMasterText { get; set; }
[MaxLength(40)]
public string ShortDescription { get; set; }
public string MasterDescriptionLine1 { get; set; }
public string MasterDescriptionLine2 { get; set; }
public string MasterDescriptionLine3 { get; set; }
public string LanguageCode { get; set; }
}
No modifications has been done to these entities using fluent API.
Now, whenever I try to insert object of type ProjectRequest with Materials and Translations nested in it, in Translation objects ProjectRequestId is set to 0.
Following is sample Change Tracker snapshot:
Can anyone help me on this? Why ProjectRequestId is 0 but MaterialId properly assigned in Transaltion objects?

IAsyncEnumerable cannot be used for parameter of type IEnumerable

I have entities, service and view models. I use the service models in the services and in the service I map from entity to the service model and I return IQueryable<UserServiceModel> and I use the service in the controller but when I try to materialize the result and map it to the view model with Select it throw exception:
ArgumentException: Expression of type 'System.Collections.Generic.IAsyncEnumerable1[TestDriveServiceModel]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable1[TestDriveServiceModel]' of method 'System.Collections.Generic.List1[TestDriveServiceModel] ToList[TestDriveServiceModel](System.Collections.Generic.IEnumerable1[TestDriveServiceModel])'
Parameter name: arg0
// the service map from entities to service models and returns them
// userServiceModels is the result of the service
// Here the error is thrown
var viewModel = await userServiceModels.Select(usm => new UserViewModel()
{
TestDrivesCount = usm.TestDrives.Count()
}).ToListAsync();
public class UserServiceModel : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<TestDriveServiceModel> TestDrives { get; set; } = new List<TestDriveServiceModel>();
}
public class TestDriveServiceModel
{
public string Id { get; set; }
public string CarId { get; set; }
public CarServiceModel Car { get; set; }
public string UserId { get; set; }
public UserServiceModel User { get; set; }
public string StatusId { get; set; }
public StatusServiceModel Status { get; set; }
public DateTime ScheduleDate { get; set; }
public string Comment { get; set; }
}
public class User : IdentityUserEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<TestDriveEntity> TestDrives { get; set; } = new List<TestDriveEntity>();
}
public class TestDriveEntity
{
public string Id { get; set; }
[Required]
public string CarId { get; set; }
public BaseCarEntity Car { get; set; }
[Required]
public string UserId { get; set; }
public User UserEntity { get; set; }
[Required]
public string StatusId { get; set; }
public Status StatusEntity { get; set; }
[Required]
public DateTime ScheduleDate { get; set; }
public string Comment { get; set; }
}

The Entity Framework created own columns for foreign keys

The Entity Framework ignores my foreign keys and creates own. How I can solve this problem?
I have few classes:
[Table("Entity")]
public class Entity
{
public Entity()
{
HeavyEntities = new List<HeavyEntity>();
}
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityId { get; set; }
public string Name { get; set; }
public ICollection<HeavyEntity> HeavyEntities { get; set; }
}
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
public int? TargetEntityId { get; set; }
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}
[Table("Tech")]
public class Tech : Entity
{
public string Status { get; set; }
}
[Table("Company")]
public class Company : Entity
{
public string Country { get; set; }
}
Create and save entities:
var (context = new MyDbContex())
{
var tech = new Tech
{
Name = "Tech1",
Status = "New",
};
var company = new Company
{
Name = "Company1",
Country = "Ukraine"
};
tech.HeavyEntities.Add(new HeavyEntity
{
Relation = Relation.AsParent,
TargetEntity = company,
});
context.Techs.Add(tech);
context.Companies.Add(company);
context.SaveChanges();
}
For this classes Entity Framework creates the following table (HeavyEntity):
How I can map foreign keys to my fields?
SOLVED:
[Table("Entity")]
public class Entity
{
public Entity()
{
HeavyEntities = new List<HeavyEntity>();
}
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityId { get; set; }
public string Name { get; set; }
[InverseProperty("Entity")]
public ICollection<HeavyEntity> HeavyEntities { get; set; }
}
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
[ForeignKey("EntityId")]
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
[ForeignKey("TargetEntityId")]
public int? TargetEntityId { get; set; }
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}
Add the ForeignKey attribute.
see https://msdn.microsoft.com/en-us/data/jj591583#Relationships
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
public int? TargetEntityId { get; set; }
[ForeignKey("TargetEntityId")] // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}

Entity Framework 4.3 CF many - to - many relationship saving object?

When creating many to many relationship using EF 4.3 code first approach, I cannot save data to connecting table, also cannot any examples on how to fill this table using saving object to Icollection... Here is my example:
MODELS
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
}
public class Project: DbContext
{
public DbSet<Hospital> Hospitals { get; set; }
public DbSet<Operator> Operators { get; set; }
}
CONTROLLER
public void AddOperater()
{
Hospital h = new Hospital();
h = db.Hospitals.Single(a=>a.Id ==1);
var o = new Operator();
o.FirstName = "John";
o.LastName = "Doe";
o.Dob = new DateTime(1988,2,12);
o.Email = "johndoe#gmail.com";
o.Hospitals.Add(h);
db.SaveChanges();
}
With this approach I keep getting error here: o.Hospitals.Add(h); even when my Hospital instance is filled with data. How exactly to save data to both tables, the dbo.Operators and dbo.OperatorHospital which is relationship table?
o.Hospitals.Add(h) will fail because the list is a null list. You cannot call Add() on a null list. Typically most people get around this by instantiating the list in the constructor of the entity... like so... the current line is blowing up due to a CSharp issue.
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
public Hospital()
{
Operators = new List<Operator>();
}
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
public Operator()
{
Hospitals = new List<Hospital>();
}
}

How to use CodeFirst (EntityFramework, Microsoft) to make nullable complex column

I've got a definition like below and essentially, I want to create this in the EmailAccount class:
public EmailUser? EmailUserAccountInfo {get;set;}
the compiler gives me an error about non-nullable types. My goal is I want to make the EmailUser optional. I'm kind of confused because I can set EmailUserAccountInfo = null directly.
var r = new EmailAccount()
{
EmailUserAccountInfo = null,
Id = 1001
};
public class EmailAccount
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public EmailUser EmailUserAccountInfo { get; set; }
}
public class EmailUser
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public EmailAccount EmailAcount { get; set; }
public string EmailAddress { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string State { get; set; }
public int Temperature { get; set; }
public string WeatherString { get; set; }
public ImageDetail ImageOfUser { get; set; }
}
You can do this if you add a foreign key and you mark that nullable:
public class EmailAccount
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// Foreign key
public int? EmailUserAccountInfoId { get; set; }
// Navigation property
public virtual EmailUser EmailUserAccountInfo { get; set; }
}
See this document about naming conventions for Code-First. (Scroll down to Relationship Convention)