Can someone please help me with mapping the following hierarchy with EF 6 code first? I can find anything useful for the below example in the documentation.
namespace Contacts {
public class Person
{
public Person()
{
this.Emails = new HashSet<Email>();
}
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Email> Emails { get; set; }
}
public class Company
{
public Company()
{
this.Emails = new HashSet<Email>();
}
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Email> Emails { get; set; }
}
public class Email
{
public string Value { get; set; }
public string Label { get; set; }
public string TargetId { get; set; }
public string TargetType { get; set; }
}
}
TargetType can be set to Company or Person depending on the entity that contains the Email instance.
DB Schema:
Related
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; }
}
Here are my models:
public partial class UserDTO
{
public int UserId { get; set; }
public ICollection<Userskills> Userskills { get; set; }
}
public partial class SkillsmasterDTO
{
public sbyte SkillId { get; set; }
public string Skill { get; set; }
public ICollection<Userskills> Userskills { get; set; }
}
public partial class UserskillsDTO
{
public int UserId { get; set; }
public sbyte SkillId { get; set; }
public SkillsmasterDTO Skill { get; set; }
public UsermasterDTO User { get; set; }
}
public class UserMaster
{
public int UserId { get; set; }
public List<UserSkills> UserSkills{get;set;}
//other fields
}
public class SkillsMaster
{
public sbyte SkillId { get; set; }
public string Skill { get; set; }
}
public class UserSkills
{
public int UserId { get; set; }
public sbyte SkillId { get; set; }
public string Skill { get; set; }
}
I want to save UserMaster, and along with that I want to save UserSkills also.
I am sending data in following format:
{"FirstName": "Priya",
"LastName": "Dave",
"Email":"priya.dave#xyz.com",
"Password":"123456",
"ContactNo":"1234",
"RoleId":1,
"CreatedBy":15,
"UserTypeId":2,
"LocationId":1,
"BandId":1,
"PostId":1,
"IsActive":1,
"UserSkills":[{"SkillId":1}]
}
Code I've written for save is:
var insertedEmployee= unitOfWork.UserRepository.Add(Mapper.Map<Usermaster>(employee));
_unitOfWork.Save();
It is saving user details but UserSkills is not getting saved. How can I do that? I went through some blogs but not able to find proper solution.
Because UserSkills is persisted in a different table than UserMaster, you need to do the following for a unit of work.
Add UserMaster to context.UserMasters table
Add UserSkills to context.UserSkills table
Add UserSkills to context.UserMaster object
Then context.SaveChanges()
My issue is the following. I have a Model for an Address table as follows.
public partial class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
This ADDRESS model is used throughout my application and has different validation requirements depending on where it is placed within a form.
I am wondering if there is a way to customize the data annotations. For example, the ADDRESS_LINE and CITY properties are required for OCCUPATION_ADDRESS but not required for WORK_LOCATION_ADDRESS.
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
Or it could be that basic validation is the same (zip has to be 5 digits), but I need to adjust the "DisplayName" that is used to match the label of the form it is within.
Trying to minimize the amount of copied models I have set up; otherwise maintenance will be a nightmare.
you can achieve this by using the idea of inheritance
how?
public abstract class ADDRESS
{
public ADDRESS()
{
this.ADDRESS_ID = Guid.NewGuid();
}
public Guid ADDRESS_ID { get; set; }
public string ADDRESS_LINE { get; set; }
public string CITY { get; set; }
public Guid? STATE_ID { get; set; }
public string ZIP { get; set; }
}
public parital class OCCUPATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(string.IsNullOrWhiteSpace(ADDRESS_LINE))
yield return new ValidationResult("Address line is required!",new string[]{"ADDRESS_LINE"});
}
}
public parital class WORK_LOCATION_ADDRESS: ADDRESS,IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
}
}
// and your Occupation details class will be like: instead of ADDRESS you will use the corresponding derived classes
public class OCCUPATION_DETAILS
{
public string COMPANY_NAME { get; set; }
public string JOB_TITLE { get; set; }
etc...
public Guid OCCUPATION_ADDRESS_ID { get; set; }
public virtual OCCUPATION_ADDRESS OCCUPATION_ADDRESS { get; set; }
public WORK_LOCATION_ID { get; set; }
public virtual WORK_LOCATION_ADDRESS WORK_LOCATION_ADDRESS { get; set; }
}
and the inheritance should be Table per Hierarchy (TPH)
for more information about TPH check this Table per hierarchy
hope that this will help you
regards
I have a very small object graph that I'm using:
public struct Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
etc...
}
public class User
{
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
public string FirstName { get; set; }
etc...
}
Using Entity Framework 4.1, how would I map this structure to one table so that they're mapped to columns like:
HomeAddressLine1
HomeAddressLine2
WorkAddressLine1
WorkAddressLine2
FirstName
LastName
etc...
EF doesn't support structures. You must use class for your Address and map it as complex type:
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
}
public class User
{
public int Id { get; set; }
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
public string FirstName { get; set; }
}
public class Context : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.HomeAddress.AddressLine1)
.ColumnName("HomeAddressLine1");
// Use the same pattern for all columns of HomeAddress and WorkAddress
}
}
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>();
}
}