Mapping IdentityUser derived to a concrete class with AutoMapper - entity-framework

I have a simple AspNetCore Web Api with 2 entities a Product and a Person which derives from IdentityUser
public class Product
{
public int Id {get;set;}
public string Name {get; set;}
public Person Person {get; set; }
}
public class Person : IdentityUser
{
public string FirstName {get; set;}
}
And the ViewModel and the AutoMapper profile
public class ProductVM
{
public string Name {get; set;}
public string PersonWhoAdded {get;set;}
}
public class ProductProfile : Profile
{
public ProductProfile()
{
CreateMap<Product, ProductVM>()
.ForMember(p=> PersonWhoAdded , opt.MapFrom(model=>model.Person.FirstName)).ReverseMap();
}}
And here is my repo
`public class ProductRepo: IProductRepo
{
public IEnumerable<Product> GetProducts()
{
return context.ProductSet.Include(p=> p.Person).ToList();
}
}`
And my controller
[Route("api/[controller]")
public class ProductController: Controller
{
IMapper _mapper;
ctor(mapper){
_mapper=mapper;
}
[HttpGet]
public IActionResult Get()
{
IEnumerable<Product> _products = _repo.GetProducts();
// omitted Status codes for simplicity
return Ok(_mapper.Map<IEnumerable<ProductVM>>(_products);
}
}
The problem is it shows me null on personWhoAdded instead of the FirstName
I can authenticate and do PUSH from different users after I register and login but if I want a get to list the products and the firstName of the User it shows me null ...
Maybe there's a different approach but I am not an expert so any help would do
Thanks

Related

Foriegn Key from multiple tables on a single column EF code First

I am using EF version 6.1 and have a mapping problem:
class BasePoco
{
public Guid Id{get;set;}
}
class Student : BasePoco
{
public string Name;
}
public class UserBase : BasePoco
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string Photo { get; set; }
}
public class UserDetail : UserBase
{
public string MobileNumber { get; set; }
public string EmailID { get; set; }
}
public Enum UserType
{
Student = 1,
User=2
}
the Attendance class
public class Attendance
{
public class UserId {get;set;} // Can be either student or user
public UserType UserType {get;set;}
}
I need to mark attendance for Student as well as User in the same table.
The UserType would determine whether the Id is of a student or User and the primary key would be a combination of UserType and Id.
How can I accomplish this using EF code first approach.
Sorry you cant use multiple type over single property. You do understand, because EF run over metadata. Which use EF know metadata from model class. This is a problem. Attendance table foregin key is multiple table referance and Attendance model contains both model. You should create logical layer for check UserType and access correct model. For example
public class Attendance
{
public UserType userType {get;set;}
public Guid? UserId {get;set;}
public virtual User user {get;set;}
public Guid? StudentId {get;set;}
public virtual Student student {get;set;}
}
now layer class
public class AttendanceUserLayer
{
public static object GetUser(Attendance attendance) {
if (attendance.userType == UserType.User) {
return attendance.User;
} else {
return attendance.Student;
}
}
how to use
Attendance attendance = context.Attendance.FirstOrDefault();
var userOrStudent = AttendanceUserLayer.GetUser(attendance);
if you cannot use the type of object result, write interface both class and set return type that interface.

Entity Framework Code First Include Method and missing Navigation Property

I have the following (abbreviated) DbContext:
public class O19Context : BaseContext<O19Context>
{
public DbSet<PRJ> O19Set { get; set; }
}
[Table("AUFK")]
public class AUFK
{
[ForeignKey("PRJ_GUID")]
public PRJ PRJ {get; set;}
[Key]
public Guid AUFK_GUID {get; set;}
}
[Table("PRJ")]
public class PRJ
{
[Key]
public Guid PRJ_GUID {get; set;}
public IQueryable<AUFK> AUFKS {get; set;}
}
When I run the following code:
var db = new O19Context();
var prj = db.O19Set.Include("AUFKS")
.Single(o => o.PRJ_GUID ==
new Guid("6FE5E97B-9970-4E24-B051-9A710C03A030"));
I get an invalid Include path error. The EntityType PRJ does not declare a navigation property with the name AUFKS.
Where am I going wrong?
Pamela
A good way to see if EF likes your POCO is the EF Power Tools "View Entity Data Model (Read Only)".
http://www.infoq.com/news/2013/10/ef-power-tools-beta4
I made two changes to your code and it now creates a little diagram...
[TestClass]
public class O19Tests
{
[TestMethod]
public void O19Test1()
{
var db = new O19Context();
var prj = db.O19Set.Include("AUFKS")
.FirstOrDefault(o => o.PRJ_GUID ==
new Guid("6FE5E97B-9970-4E24-B051-9A710C03A030"));
}
}
public class O19Context : DbContext//<O19Context>
{
public DbSet<PRJ> O19Set { get; set; }
}
[Table("AUFK")]
public class AUFK
{
//[ForeignKey("PRJ_GUID")] //remove this...
//there is no PRJ_GUID field IN THIS CLASS
public PRJ PRJ { get; set; }
[Key]
public Guid AUFK_GUID { get; set; }
}
[Table("PRJ")]
public class PRJ
{
[Key]
public Guid PRJ_GUID { get; set; }
public IList<AUFK> AUFKS { get; set; } //use IList
}
A navigation property must implement ICollection<T> - you define the property as IQueryable<T> which I do not believe is supported

Is it possible to have an InverseProperty refer to a property on a complex type

Is it possible to have an inverseproperty refer to a property on a complex type?
This is a contrived example that shows the structure of what I want to do:
public class MyType {
public MyName Name { get; set; }
}
[ComplexType]
public class MyName {
public int ProfileId {get; set;}
[ForeignKey("ProfileId")]
public Profile Profile{get; set;}
}
public class Profile
{
[InverseProperty("Name.Profile")]
public virtual IList<MyType> MyTypes{ get;set;}
}

Entity Framework Code First Map (Linked) Table?

I'm working with the EF code first approach and want to add a link (map) table. I am working off the below example and get the following error:
System.Data.Entity.Edm.EdmEntityType: : EntityType 'EmployeeDepartmentLink' has no key defined. Define the key for this EntityType.
Problem is I dont want a key on this table it just maps the two tables together:
public class Employee
{
[Key()]
public int EmployeeID;
public string Name;
}
public class Department
{
[Key()]
public int DepartmentID;
public string Name;
}
public class EmployeeDepartmentLink
{
public int EmployeeID;
public int DepartmentID;
}
I have tried a variety of things like adding the "[Key()]" attribute but it doesn't make sense for it to be used, and which field do I add it to? I am wondering if this sort of table model is even supported?
You are trying to make a "Many to Many" mapping.
To perform this, write this code:
public class Employee
{
[Key]
public int EmployeeId;
public string Name;
public List<Department> Departments { get; set; }
public Employee()
{
this.Departments = new List<Department>();
}
}
public class Department
{
[Key]
public int DepartmentId;
public string Name;
public List<Employee> Employees { get; set; }
public Department()
{
this.Employees = new List<Employee>();
}
}
then, in your DbContext:
public class YourContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public YourContext() : base("MyDb")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().
HasMany(c => c.Employees).
WithMany(p => p.Departments).
Map(
m =>
{
m.MapLeftKey("DepartmentId");
m.MapRightKey("EmployeeId");
m.ToTable("DepartmentEmployees");
});
}
}
For M:M relationship you have to create your join (link) class is as below.
public class EmployeeDepartmentLink
{
[Key, Column(Order = 0)]
public int EmployeeID;
[Key, Column(Order = 1)]
public int DepartmentID;
}
For more information check Create code first, many to many
I hope this will help to you.

When Entity Framework auto generated property gets populated

Consider I have the following classes:
class User
{
[Key]
public Guid Id {get; set;}
public string UserName {get; set;}
}
class MyUsersContext: DbContext
{
DbSet<User> Users {get; set;}
}
class MyRepository
{
MyUsersContext _db; //INJECTED
User AddUser(string userName)
{
var newBorn = new User() { UserName = userName };
_db.Users.Add(newBorn);
return newBorn;
}
}
class MyMemProvider: MembershipProvider
{
MyRepository repo; //INJECTED
public override MembershipUser CreateUser(string username...
{
var ret = repo.AddUser(username);
return new MembershipUser(System.Web.Security.Membership.Provider.Name, ret.UserName...
}
}
This is a stripped down version of my custom membership provider for ASP.NET MVC3 site. At what point User.Id gets filled with actual Guid in this scenario?
You have to apply DatabaseGeneratedOption on your Id attribute.
class User
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id {get; set;}
public string UserName {get; set;}
}