My Order class
public class Order
{
[Key]
public int ID { get; set; }
(...)
[ForeignKey("Client")]
public string ClientID { get; set; }
public virtual ApplicationUser Client { get; set; }
[ForeignKey("Trader")]
public string TraderID { get; set; }
public virtual ApplicationUser Trader { get; set; }
[ForeignKey("Driver")]
public string DriverID { get; set; }
public virtual ApplicationUser Driver { get; set; }
}
And my MS Identity ApplicationUser class:
public class ApplicationUser : IdentityUser
{
(...)
public virtual List<Order> Orders { get; set; }
}
As you can see I'd like to have speciffic users in speciffic "role" in Order model. How should I write a code in ApplicationUser to get speciffic lists of Clients, Traders and Drivers? I mean, I'd like to find user in database and then I'd like to have three lists named e.g. AsClient, AsTrader and AsDriver. Right now List<Orders> count is always 0.
Use InversePropertyAttribute:
public class ApplicationUser : IdentityUser
{
//another stuff...
[InverseProperty("Client")]
public virtual ICollection<Order> AsClient { get; set; }
[InverseProperty("Trader")]
public virtual ICollection<Order> AsTrader { get; set; }
[InverseProperty("Driver")]
public virtual ICollection<Order> AsDriver { get; set; }
}
I would suggest you use a little inheritance here.
So you would create three classes that extend ApplicationUser, one for each Trader, Client and Driver. And then on each of these classes have the orders list. Also, on the Order class, change the types from ApplicationUser to the appropriate subtype.
Then as an inheritance strategy you can choose the table per hierarchy and follow the instructions on this link to implement it.
Hope this helps.
Related
Is it possible to build two optional one-to-one relationship in SQL?
I'd like to have:
public class EventInvoice
{
[Key]
public int ID { get; set; }
[ForeignKey("SZ_Event")]
public Nullable<int> SZ_EventID { get; set; }
public virtual SzopbudkaEvent SZ_Event { get; set; }
[ForeignKey("UP_Event")]
public Nullable<int> UP_EventID { get; set; }
public virtual Event UP_Event { get; set; }
}
public class Event
{
[Key]
public int EventID { get; set; }
public virtual EventInvoice EventInvoice { get; set; }
}
public class SzopbudkaEvent
{
[Key]
public int ID { get; set; }
public virtual EventInvoice EventInvoice { get; set; }
}
My invoice can be combined only with one of those objects (Event or SzopbudkaEvent). Is it possible to use it like this or I have to write something different?
You can do this but there are two things to bear in mond.
If the constraint is only one of the FK's can exist, then in the database the FK columns on the EventInvoice tale must be nullable. You've got this but I thought I'd emphasise it.
If there is also a constraint that there must be one of them (missing both is not allowed) then you have to work out how to validate that constraint. In the DB I'd use a trigger fir insert, update that raises an exception if both are null. I'd match that in code with a pre-save check: this describes implementing interface IValidatableObject with a Validate method which EF will call when the object is affected by SaveChanges.
i am trying to define a database model in code-first to see and display which user is assigned as a specialist for the record data.
I have a very simple model for the user:
public class User
{
public int ID { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
....
}
Next I have defined two (simple) models which define the data that can be edited by the user and the specialist should be assigned to using a dropdownlist:
public class Order
{
public int ID { get; set; }
public string orderNumber { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
public class Part
{
public int ID { get; set; }
public string partNumber { get; set; }
public string description { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
What kind of relation between the models can be used without having a navigation property for each table in the User model?
Do I need to use additional tables to define the relationship: User.Id-Order.specialistID and the relationship: User.Id-Part.specialistID ?
Is there a smarter way out-of-the-box by Entity Framework?
Many thanks for your answers.
Pascal
By default when you add forign-key constraint to the many-to-one table the Entity Framework add virtual property to the entity class and virtual ICollection to the User.
I have my ApplicationUser model defined like so:
public class ApplicationUser : IdentityUser
{
public virtual UserProfileInfo UserProfileInfo { get; set; }
}
With UserProfileInfo being an auxiliary table containing extra user data, defined as such:
public class UserProfileInfo
{
public int Id { get; set; }
public string SuperiorId { get; set; }
[ForeignKey("SuperiorId")]
public virtual ICollection<ApplicationUser> Superior { get; set; }
}
Each user has one or more people who are superior to them, in a business hierarchy. However, attempting to do a migration results in the following error:
The ForeignKeyAttribute on property 'Superior' on type 'Project.Models.UserProfileInfo' is not valid. The foreign key name 'SuperiorId' was not found on the dependent type 'Project.Models.ApplicationUser'.
How can I make a foreign key reference to ApplicationUser in my situation?
You need to do it the other way around, the ID is the foreignkey of the navigational property:
public class UserProfileInfo
{
public int Id { get; set; }
[ForeignKey("Superior")]
public string SuperiorId { get; set; }
public virtual ICollection<ApplicationUser> Superior { get; set; }
}
i want something like this :
public class Order
{
public Guid OrderID { get; set; }
public Guid UserId { get; set; }
public DateTime OrderDate { get; set; }
public decimal Amount { get; set; }
public virtual ICollection<OrderDetail> orderDetailByOrderID { get; set; }
public virtual MembershipUser userByOrderID { get; }
}
so from above code i want membership user to be access from Order object ....
however i tried it but its not working.
so please suggest some solution if you have come across this type situation
It sounds like you might be using Entity Framework Code First. If this is the case you'd probably want:
public virtual aspnet_Membership userByOrderID { get; set; }
instead of
public virtual MembershipUser userByOrderID { get; }
That would grab the aspnet_Membership entity that is tied to the UserId foreign key. The aspnet_Membership class is not quite the same as the MembershipUser entity, but they have many of the same properties.
If that won't work, you can always use your Order model as is, and generate a ViewModel that has the MembershipUser object.
public class OrderViewModel
{
public Order Order { get; set; }
public MembershipUser User { get; set; }
}
and create the ViewModel like this before passing it into a view
Order order = EntityDataContext.Orders.First();
var model = new OrderViewModel { Order = order, User = Membership.GetUser(order.UserId) }
I am building a reservation system. I have users in roles('admin', 'client', 'employee', 'student').
Each reservation must be associated with a user of role client, it might be assigned to user of role employee and might also be assigned to user of role student.
So in my reservation class I have properties of type User and I have marked them with [ForeignKey("AnytypeId")] attribute to hint EF for relations.
I have seen code like this at http://blog.stevensanderson.com/2011/01/28/mvcscaffolding-one-to-many-relationships/
public class Reservation
{
public int ReservationID
{
get;
set;
}
[Required(ErrorMessage="Please provide a valid date")]
public DateTime ReservationDate
{
get;
set;
}
public DateTime ReservationEnd { get; set; }
public DateTime EntryDate
{
get;
set;
}
public DateTime UpdatedOn
{
get;
set;
}
public decimal Ammount
{
get;
set;
}
public decimal? Discount { get; set; }
[DataType(DataType.MultilineText)]
public string ServiceDetails { get; set; }
[DataType(DataType.MultilineText)]
public string Remarks { get; set; }
public String PaymentMethod { get; set; }
public string VoucherNumber { get; set; }
public int ServiceID
{
get;
set;
}
public virtual Service Service
{
get;
set;
}
public string EmployeeID { get; set; }
[ForeignKey("EmployeeID")]
public virtual User Employee { get; set; }
public string ClientID { get; set; }
[ForeignKey("ClientID")]
public virtual User Client { get; set; }
public string StudentID { get; set; }
[ForeignKey("StudentID")]
public virtual User Student { get; set; }
}
public class ReservationMap : EntityTypeConfiguration<Reservation>
{
public ReservationMap()
{
this.HasOptional(r => r.Client).WithMany().WillCascadeOnDelete(true);
this.HasOptional(r => r.Employee).WithMany().WillCascadeOnDelete(false);
this.HasOptional(r=>r.Student).WithMany().WillCascadeOnDelete(false);
}
}
Now as I run my mvc3 EF code first app database created for me on the fly with following ERD and edmx model.
Now few problems that I am having:
1. When I am listing all the users of role clients in view their reservation property is showing always 0 even if their are reservations available in database. I don't know why this collection property marked with virtual is not loading??
Please I am stuck with this help me out here this is the last thing remaining.
There are couple of problems in your model. You have configured the one to many relationship in such a way that the many end(Reservations property) is excluded from the mapping. Hence the Reservations will not be loaded by EF.
The other problem is if you are going to map the Reservations property as the many end of the relationship, what will be the navigational property? is it Employee, Client, Student? Because only one of these properties can participate in the relationship with Reservations property.
It is not clear as to how these relationships should be modeled by your description. One way would be to have 3 collection properties.
public class ReservationMap : EntityTypeConfiguration<Reservation>
{
public ReservationMap()
{
HasOptional(r => r.Client).WithMany(u => u.ClientReservations).WillCascadeOnDelete(true);
HasOptional(r => r.Employee).WithMany(u => u.EmployeeReservations).WillCascadeOnDelete(false);
HasOptional(r=>r.Student).WithMany(u => u.StudentReservations).WillCascadeOnDelete(false);
}
}