In my previous question, I've mentioned that I'm developing a Point of Sale application. The platforms I use are WPF, MVVM and Entity Framework (code-first). Since Entity Framework code-first has its own logic to map entities and relations, I'm confused about a case.
I have an EntityBase class:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public User CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public User UpdatedBy { get; set; }
}
public class User : EntityBase
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Since User class has EntityBase class members, will it arise problems at database side?
Or should I keep the data like this:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public int CreatedByUserId { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UpdatedByUserId { get; set; }
}
Create your models in this way:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public int CreatedById { get; set; }
[ForeignKey("CreatedById")]
public User CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UpdatedById { get; set; }
[ForeignKey("UpdatedById")]
public User UpdatedBy { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Related
How can I track created and modified date automatically in C# with MongoDB.
I have database:
public class BaseEntity
{
public DateTime? DateCreated { get; set; }
public string UserCreated { get; set; }
public DateTime? DateModified { get; set; }
public string UserModified { get; set; }
}
public class Income : BaseEntity
{
public Guid Id { get; set; }
[DisplayName("Income")]
public string Income_ { get; set; }
public string Date { get; set; }
public String Description { get; set; }
}
I want to track DateCreated and DateModified automatically.
I am using Entity framework. I am using inheritance, which puts different object types in the same table (via discriminator).
However, this causes an issue as relationships between objects in the same table can not be illustrated via a foreign key. Any suggestions how to solve? Some code below.
public abstract class DivBase
{
public int Id { get; set; }
[Required]
public DateTimeOffset DateCreated { get; set; }
[Required]
public int CreatedByUserId { get; set; }
[Required]
public DateTimeOffset DateModified { get; set; }
[Required]
public int ModifiedByUserId { get; set; }
}
public abstract class DivClaim : DivBase
{
[Required]
[MaxLength(256)]
public string ClaimType { get; set; }
[Required]
[MaxLength(256)]
public string Name { get; set; }
[MaxLength(10000)]
public string Description { get; set; }
public ICollection<DivUserClaim> UserClaims { get; set; }
}
public class DivCustomer : DivClaim
{
public ICollection<DivProject> Projects { get; set; }
}
public class DivProject : DivClaim, IDivEvent
{
public int CustomerId { get; set; }
public DivCustomer Customer { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
}
In this case where your base class just defines common attributes for all your entities, simply exclude the base class from the DbContext. Each of your Entities will get its own table, but they will all have the properties inherited from the base class. You just won't be able to query over the base entity type.
I want to map from
LDTTicketUploadDTO[] to IEnumerable<LDTTicket>
The mappings are created in this method and at the end I map the data.
public void UploadLDTTickets(LDTTicketUploadDTO[] ticketDTOs)
{
Mapper.CreateMap<LDTTicketUploadDTO, LDTTicket>();
Mapper.CreateMap<LDTTicketDTO, LDTTicket>();
Mapper.CreateMap<LDTCustomerDTO, LDTCustomer>();
Mapper.CreateMap<LDTDeviceDTO, LDTDevice>();
Mapper.CreateMap<LDTUnitDTO, LDTUnit>();
Mapper.CreateMap<LDTCommandDTO, LDTCommand>();
Mapper.CreateMap<LDTCommandParameterDTO, LDTCommandParameter>();
Mapper.CreateMap<LDTObjectDTO, LDTObject>();
Mapper.CreateMap<LDTControlFileDTO, LDTControlFile>();
Mapper.CreateMap<LDTDeviceDTO, LDTDevice>();
Mapper.CreateMap<LDTLanguageDTO, LDTLanguage>();
Mapper.CreateMap<LDTObjectBitDTO, LDTObjectBit>();
var tickets = Mapper.Map<IEnumerable<LDTTicketUploadDTO>, IEnumerable<LDTTicket>>(ticketDTOs);
// do something with tickets
}
This is how the DTO´s are structured:
public class LDTTicketUploadDTO
{
public LDTTicketDTO Ticket { get; set; }
public LDTDeviceDTO Device { get; set; }
public LDTCustomerDTO Customer { get; set; }
}
public enum TicketStatus
{
New,
InProgress,
Done
}
public class LDTTicketDTO
{
public bool UploadNeeded { get; set; }
public string TicketNumber { get; set; }
public TicketStatus Status { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public string AssignedTo { get; set; }
public IEnumerable<LDTUnitDTO> Units { get; set; }
}
public class LDTUnitDTO
{
public int Id { get; set; }
public string FunctionUnit { get; set; }
public int FunctionUnitAddress { get; set; }
public string Zone { get; set; }
public int ZoneUnitAddress { get; set; }
public string Object { get; set; }
public int ObjectAddress { get; set; }
public IEnumerable<LDTCommandDTO> Commands { get; set; }
}
and more...
What works is that these properties are correctly mapped to their counterpart entities:
public LDTDeviceDTO Device { get; set; }
public LDTCustomerDTO Customer { get; set; }
What works NOT is that this property is not mapped:
public LDTTicketDTO Ticket { get; set; }
This is how the Entities are structured:
public class LDTTicket
{
[Key, Column(Order = 0)]
[Required]
public string SerialNumber { get; set; }
[Key, Column(Order = 1)]
[Required]
public string TicketNumber { get; set; }
[Required]
public DateTime CreatedOn { get; set; }
[Required]
public string AssignedTo { get; set; }
public TicketStatus Status { get; set; }
public string CreatedBy { get; set; }
public bool UploadNeeded { get; set; }
public virtual LDTCustomer Customer { get; set; }
public virtual LDTDevice Device { get; set; }
public virtual ICollection<LDTUnit> Units { get; set; }
}
ONLY the Customer and Device property are mapped in the LDTTicket
What is wrong with my configuration?
It's expecting to populate a LDTTicket sub-property on the ticket, not the matching properties of the ticket itself. Create direct mappings onto the ticket from the Ticket subproperty of the source directly onto the matching properties of the destination. NOTE: You only need to define your mappings once, not per method execution. Mappings should be defined at app start up and thereafter used.
public void UploadLDTTickets(LDTTicketUploadDTO[] ticketDTOs)
{
Mapper.CreateMap<LDTTicketUploadDTO, LDTTicket>();
.ForMember(d => d.SerialNumber, m => m.MapFrom(s => s.Ticket.SerialNumber))
...
//Mapper.CreateMap<LDTTicketDTO, LDTTicket>(); You don't need this
Mapper.CreateMap<LDTCustomerDTO, LDTCustomer>();
Mapper.CreateMap<LDTDeviceDTO, LDTDevice>();
...
}
I created:
custom custom membership provider
custom role provider
an user model
an role model
It create me the 2 custom tables correctly.
Now I want to create the table between Users and Roles with 2 columns: RoleId, UserId
I should I tweak my models to teach to EF to create this relationship table (UsersInRole)?
User model:
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public Int32 CompanyId { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
public String PasswordSalt { get; set; }
public String Email { get; set; }
public Boolean IsApproved { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime LastLockoutDate { get; set; }
}
Role model:
public class Role
{
[Key]
public int RoleId { get; set; }
[Required]
[MaxLength(20)]
public string Name { get; set; }
public ICollection<string> AssignedUsers { get; set; }
}
If you are using code-first EF, then all you should need to do is add a collection of the Users to the Role class and vice-versa. EF takes this two-way link as a signal to create a many-to-many relationship in the underlying data store. To summarize, your classes would be augmented something like this...
public class User
{
...
List<Role> Roles {get; set;}
}
public class Role
{
...
List<User> Users {get; set;}
}
public class Role
{
[Key]
public int RoleId { get; set; }
[Required]
[MaxLength(20)]
public string Name { get; set; }
public ICollection<User> AssignedUsers { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public Int32 CompanyId { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
public String PasswordSalt { get; set; }
public String Email { get; set; }
public Boolean IsApproved { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime LastLockoutDate { get; set; }
public ICollection<Role> Roles{ get; set; }
}
I am having trouble with SQL Server creating Foreign Key constraints when using Entity Framework Code First.
This is my scenario. I am building an application which allows us to log tickets against any of our systems and automatically assign the ticket to the relevant person.
We have Services, which can have many categories. The categories can have many subcategories. A help desk person can be assigned to Service, and Category or Subcategory.
Here are my classes:
Service.cs
public class Service
{
[Key]
public int ServiceID { get; set; }
public string Title { get; set; }
public DateTime CreatedDate { get; set; }
public HelpDeskMember CreatedBy { get; set; }
public DateTime? DeletedDate { get; set; }
public HelpDeskMember DeletedBy { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subcategory> Subcategories { get; set; }
public virtual ICollection<HelpDeskMember> LinesOfSupport { get; set; }
}
Category.cs
public class Category
{
[Key]
public int CategoryID { get; set; }
[ForeignKey("Service")]
public int ServiceID { get; set; }
public string Title { get; set; }
public DateTime CreatedDate { get; set; }
public HelpDeskMember CreatedBy { get; set; }
public DateTime? DeletedDate { get; set; }
public HelpDeskMember DeletedBy { get; set; }
public virtual Service Service { get; set; }
public virtual ICollection<Subcategory> Subcategories { get; set; }
public virtual ICollection<HelpDeskMember> LinesOfSupport { get; set; }
}
Subcategory.cs
public class Subcategory
{
[Key]
public int SubcategoryID { get; set; }
[ForeignKey("Service")]
public int ServiceID { get; set; }
[ForeignKey("Category")]
public int CategoryID { get; set; }
public string Title { get; set; }
public DateTime CreatedDate { get; set; }
public HelpDeskMember CreatedBy { get; set; }
public DateTime? DeletedDate { get; set; }
public HelpDeskMember DeletedBy { get; set; }
public virtual Service Service { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<HelpDeskMember> LinesOfSupport { get; set; }
}
and finally HelpDeskMember.cs
public class HelpDeskMember
{
public int HelpDeskMemberID { get; set; }
public string Name { get; set; }
public bool Admin { get; set; }
public bool Available { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? LastLogin { get; set; }
public DateTime? DeletedDate { get; set; }
public DateTime? DeletedBy { get; set; }
public virtual ICollection<Service> Services { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subcategory> Subcategories { get; set; }
}
When the Database is being initialised, I am getting the following error message:
Introducing FOREIGN KEY constraint 'Subcategory_Service' on table 'Subcategories' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
I'm guessing the problem is with how I have defined the Key's and ForeignKey's. Any help appreciated. Thanks.
Depending on your needs. You can in configuration for your entity use WillCascadeOnDelete(false)1 or globally removing OneToManyCascadeDeleteConvention2.
Both can be set in OnModelCreating using ModelBuilder input parameter.