I have an EF 5/MVC 4, database first project I am working on and have created separate edmx files for certain logical functional areas of my application (UserManagement, CompanyManagement, InventoryManagement, OrderManagement). The UserProfile table is in all of the edmx files as it is there to join to the CreatedById and ModifiedById tables so you can get the actual user name. But I don't want to create additional properties and data annotations in each version of the UserProfile table, so I inherit the (what I call) "original version" of UserProfile which is in the UserManagement area which I add my additional properties and add my data annotations. Ok, still with me?
Ok, so here is the original UserProfile class that EF 5 creates (in the UserManagement area/folder):
namespace OTIS.domain.UserMgmt
{
using System;
using System.Collections.Generic;
public partial class UserProfile
{
public UserProfile()
{
this.webpages_Roles = new HashSet<webpages_Roles>();
}
public int UserId { get; set; }
public Nullable<int> AccountId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual webpages_Membership webpages_Membership { get; set; }
public virtual ICollection<webpages_Roles> webpages_Roles { get; set; }
}
}
Here is my partial class I use to add additional properties and add the data annotations:
namespace OTIS.domain.UserMgmt
{
[MetadataType(typeof(UserProfileMD))]
public partial class UserProfile : IEntity
{
public int Id
{
get
{
return this.UserId;
}
}
public string FullName
{
get
{
return this.FirstName + " " + this.LastName;
}
}
public string EntityDescription
{
get
{
return this.FullName;
}
}
public class UserProfileMD
{
public int UserId { get; set; }
[Required]
[Display(Name = "User Name")]
public string UserName { get; set; }
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Name")]
public string FullName { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
}
}
}
Now I am working with a version of UserProfile that is in the InventoryMgmt edmx, so I created a partial class of the same name and inherited from the above:
namespace OTIS.domain.InventoryMgmt
{
[MetadataType(typeof(OTIS.domain.UserMgmt.UserProfile.UserProfileMD))]
public partial class UserProfileInvnMgmt : UserProfile
{
}
}
Now also in the InventoryMgmt edmx is PO Header. Here is the EF generated class (note it references UserProfileInvnMgmt UserProfile which is the foreign key table to CreatedById):
namespace OTIS.domain.InventoryMgmt
{
using System;
using System.Collections.Generic;
public partial class POHeader
{
public POHeader()
{
this.PODetails = new HashSet<PODetail>();
}
public int Id { get; set; }
public int FacilityId { get; set; }
public int VendorId { get; set; }
public int StatusId { get; set; }
public string Notes { get; set; }
public int CreatedById { get; set; }
public System.DateTime CreatedOn { get; set; }
public int ModifiedById { get; set; }
public System.DateTime ModifiedOn { get; set; }
public virtual ICollection<PODetail> PODetails { get; set; }
public virtual Vendor Vendor { get; set; }
public virtual POHeaderStatus POHeaderStatus { get; set; }
public virtual UserProfileInvnMgmt UserProfile { get; set; }
public virtual UserProfileInvnMgmt UserProfile1 { get; set; }
}
}
Now I have a method that converts a POHeader class entity to a view model. During design time, it allows me to assign POHeader.UserProfile.FullName to the view model property OrderedBy.
public IEnumerable<POHeadersListViewModel> ConvertClassToViewModel(IEnumerable<POHeader> purchaseOrders)
{
IEnumerable<POHeadersListViewModel> poGrid =
from l in purchaseOrders.ToList()
select new POHeadersListViewModel()
{
Id = l.Id,
VendorName = l.Vendor.VendorName,
OrderedBy = l.UserProfile.FullName,
OrderDate = l.CreatedOn,
Status = l.POHeaderStatus.DisplayName
//OwnerName = l.Customer == null ? "" : l.Customer.CustomerName
};
return poGrid;
}
HOWEVER, when you run this code, no value gets assigned to OrderedBy AND if, while debugging, expand out the IEnumerable purchaseOrders variable, you see UserProfile, but if you expand it out, you DO NOT see the FullName property, but FirstName and LastName are populated. The resulting value or OrderBy in the view model is a single space, which seems like the FullName property is being returned, but that FirstName and LastName were null, resulting in FullName just returning the white space that is supposed to separate the FirstName and LastName properties, i.e.
public string FullName
{
get
{
return this.FirstName + " " + this.LastName;
}
}
But note that if I do this:
OrderedBy = l.UserProfile.FirstName + " " + l.UserProfile.LastName,
It works, so FirstName and LastName are not null. Any ideas on why FullName is not be returned correctly? In general, is the best way to to handle the multiple versions of UserProfile?