I am right now in the design phase of a new app and am doing some research. I came across the CodeFirst approach of EF 4.3 and really liked it.
However there is one design goal, I am not sure how to achieve.
Let say I have a task class:
public class TaskModel
{
public int ID { get; set; }
public string Name { get; set; }
public TaskType Task { get; set; }
}
public enum TaskType
{
Sales = 0,
Marketing = 1,
CustomerService = 2
}
I know that enums are currently not supported in EF 4.3. Hence this code would not even generate a proper database model. However I don't even need enums. Since what if the user would like to add a new TaskType at runtime?
Hence I think its best to have the TaskType as a class, which would become a table in itself and the user could add more entries. But how do I make them map together?
In such case it is common one-to-many relation:
public class TaskModel
{
public int ID { get; set; }
public string Name { get; set; }
public virtual TaskType Task { get; set; }
}
public class TaskType
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<TaskModel> TaskModels { get; set; }
}
Related
Having some issues with relationships within EntityFramework 6.
I know that DataAnnotations or FluentApi can be used and I'm okay with using either.
Here's an example of relationship I'd like to accomplish:
Student has one ImmunizationRecord
ImmunizationRecord has Multiple ShotRecords
This seems like it would be fairly straight forward, however it doesn't seem to be working as expected.
Here's example code (Updated from actual code)
public class Student : Entity
{
[Key]
public int Id { get; set; }
public String Name { get; set; }
//...
[ForeignKey(nameof(Id))]
public virtual ImmunizationRecord ImmunizationRecord { get; set; }
}
public class ImmunizationRecord : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key]
[ForeignKey(nameof(Student))]
public int StudentId { get; set; }
public String Name { get; set; }
public DateTime LastUpdated { get; set; }
public virtual Student Student { get; set; }
public virtual ICollection<ShotRecord> ShotRecords { get; set; }
}
public class ShotRecord: Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// Want this to point back to ImmunizationRecord
public int ImmunizationRecordId { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public DateTime DateOfShot { get; set; }
//...
[ForeignKey("ImmunizationRecordId")]
public virtual ImmunizationRecord ImmunizationRecord { get; set; }
}
Example fluentapi might be something like this:
modelBuilder.Entity<Student>().HasOptional(c => c.ImmunizationRecord).WithRequired(m => m.Student);
modelBuilder.Entity<Student>().HasOptional(c => c.ImmunizationRecord).WithRequired(sc => sc.Student);
modelBuilder.Entity<ImmunizationRecord>().HasMany(sc => sc.ShotRecords).WithRequired(sr => sr.ImmunizationRecord);
The Result
I suspect that I'm just missing a small piece of what needs to be done, or missing the proper way to configure these entities with a similar relationship.
With the code above and class structure, I can create a Student, and Create a ImmunizationRecord, and ShotRecords without issue.
The issue occurs when I try to retrieve the ShotRecords from The ImmunizationRecord, EntityFramework will resolve on the key on the Student.Id instead of using the key of on the ImmunizationRecord.Id.
I can go into the database and change the rows for ShotRecords and update the ImmunizationRecordId to the StudentId and they'll resolve properly. But as stated before, I want them to use the key of the ImmunizationRecord, and not the student.
Any advice and guidance would be greatly appreciated!
Thank you in advance!
(Updated to a different example to make more sense)
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'm having trouble understanding how to implement a ViewModel in Asp.net MVC, I have the following tables:
Form
ID, Data
Report
ID, FormID, Owner, Category, Status, SubmissionDate
ReportValues
ID, ReportID, Title, Value
I'm looking for a way to display and edit Report and ReportValues in the one ViewModel where ReportValues.ReportID = Report.ID
ReportValues will have multiple entries that relate to a Report.
I have had a look at similiar questions on here and tried following a tutorial ( http://techfunda.com/howto/262/list-data-using-viewmodel ) and coming up empty handed.
If you need any more information let me know and thanks in advance for any replies!
Your View Model is nothing more than a class. You can solve this many ways, but here's an example.
Create your 3 classes like you normally would.
public class Form
{
public int Id { get; set; }
public string Data { get; set; }
}
public class ReportValues
{
public int Id { get; set; }
public int ReportId { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
public class Report
{
public int Id { get; set; }
public int FormId { get; set; }
public string Owner { get; set; }
public string Category { get; set; }
public string Status { get; set; }
public DateTime SubmissionDate { get; set; }
}
Then, create your ViewModel class to include the three above classes like this.
public class ReportViewModel
{
public Form Form { get; set; }
public ReportValues ReportValues { get; set; }
public Report Report { get; set; }
}
In your view you can access your three classes and their properties as you would in your controller. Model.Form.Id
Depending on your data types, ReportValues will likely be a property of Report, but that's entirely up to your data structure. You will need to populate the classes using whatever method you want (Entity Framework, ADO, etc.) before you can pass them to your view and use them.
I am buys designing the model below:
public class LogModel
{
public class UserActivityLogs
{
[Key]
public int id { get; set; }
//Id of the user
public string userId { get; set; }
//Time of the log
public DateTime time { get; set; }
public LogActions action { get; set; }
}
// Types of actions to log
public class LogActions
{
[Key]
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
}
}
Now what I would like to know is do I need to add a table in the context for Logactions as well as UserActivityLogs or will EF see that the two tables are linked and create the log action table automatically?
Also have I specified my relationships correctly? What I was aiming for is that I can define multiple types of Logactions and then a userlog will then have a single log action associated to it.
First, don't use nested classes, it's a needless complication. Use namespaces to organize classes.
Second, don't use plural names for classes. One instance of class represents one entity. Also, use CamelCase names for properties.
Third, yes, Entity Framework will be aware of the associations between the two classes and create a database model with two tables and a foreign key.
So this leaves you with:
namespace MyApp.LogModel
{
public class UserActivityLog
{
[Key]
public int Id { get; set; }
public string UserId { get; set; }
public DateTime Time { get; set; }
public LogAction LogAction { get; set; }
}
public class LogAction
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
I feel like this should have a simple answer, but I can't find it.
I have 2 POCOs:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product
{
public int Id { get; set; }
public int CategoryId { get; set; }
}
Notice that there are no object references on either POCO. With Code-First, how do I make EF4 CTP5 define a relationship between the two database tables?
(I know this is an unusual scenario, but I am exploring what's possible and what's not with Code-First)
No, this is not possible. As you can see below, all of the fluent API methods for setting up associations require specifying the Navigation Property as their parameter.
HasMany<TTargetEntity>(Expression<Func<TEntityType, ICollection<TTargetEntity>>> navigationPropertyExpression)
HasOptional<TTargetEntity>(Expression<Func<TEntityType, TTargetEntity>> navigationPropertyExpression)
HasRequired<TTargetEntity>(Expression<Func<TEntityType, TTargetEntity>> navigationPropertyExpression)
Is there any particular reason you don't want to use object references? It looks very elegant to use them:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public Category Category { get; set; }
}
And you can still access the Category Id via your product as product.Category.Id.