zero to many relationship mapping to model - sql

I'm having a bit of an issue mapping this out to my model. I have a Question model that represents (obviously) a question, and a QuestionType that represents the types of questions possible (text, multiple choice, list, multi-line text, and so on...).
The issue i'm having right now is trying to set the options associated with each of QuestionType Model back to the Question Model. So for example, if the QuestionType was a list type, and the list contained three elements, i'm trying to join those elements back on the Question model. The problem i'm having is that not all Questions need to have the QuestionOptions variable set. For example, for just a simple text question (not shown in code).
Any suggestions on how to achieve this?
Question Model
[Table("Questions")]
public class Question {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int QuestionId { get; set; }
[Required]
public String Question { get; set; }
public int QuestionTypeId { get; set; }
[ForeignKey("QuestionTypeId")]
public virtual QuestionType QuestionType { get; set; }
public virtual ICollection<QuestionOptions> QuestionOptions { get; set; }
}
QuestionType Model
[Table("QuestionTypes")]
public class QuestionType {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int QuestionTypeId { get; set; }
[Required]
public String QuestionType { get; set; }
}
QuestionOptions Model
public abstract class QuestionOptions {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int OptionId { get; set; }
public int? QuestionId { get; set; }
[ForeignKey("QuestionId")]
public virtual Question Question { get; set; }
}
[Table("questionType_List")]
public class ListQuestion : QuestionOptions {
[Required]
public String Item { get; set; }
}
QuestionContext
public class QuestionContext : DbContext {
public QuestionContext() : base("DefaultConnection") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
Database.SetInitializer<QuestionContext>(null);
public DbSet<Question> Questions { get; set; }
public DbSet<QuestionType> QuestionTypes { get; set; }
public DbSet<ListQuestion> ListQuestions { get; set; }
}

Personally I would have QuestionOptions for all questions, even if that was a blank entry in the table or perhaps some sort of identifier that allows you to know if its multi-line or single line text.

Related

How to establish one-to-many relationship for a code-first approach?

I'm trying to build a recipe app for my spouse. I'm trying to set it up so she can add new recipes to the database as the app grows.
When adding new recipe, she will have three drop-down to pick from to construct her new recipe ingredients. First one will contain a list of ingredients that she can choose from, the second one a list of measuring units and the third one a list of quantities.
Here is what I got so far. Am I heading in the right direction or am I off? I'm using Entity Framework with a code-first approach:
public class Recipes
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
public class Units model
{
[Key]
public int Id { get; set; }
public string UnitName { get; set; }
}
public class UnitQty
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class IngredientsModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class RecipeIngredients
{
public int Id { get; set; }
public int RecipesId { get; set; }
[ForeignKey("RecipesId")]
public Recipes Recipes { get; set; }
public int IngredientsModelId { get; set; }
[ForeignKey("IngredientsModelId")]
public IngredientsModel IngredientsModel { get; set; }
public int UnitQtyId { get; set; }
[ForeignKey("UnitQtyId")]
public UnitQty UnitQty { get; set; }
public int UnitsModelId { get; set; }
[ForeignKey("UnitsModelId")]
public UnitsModel UnitsModel { get; set; }
}
After creating the table, controller and the views, this is what I get in the recipe ingredients index view.
Any suggestion will be more than welcome please and thank you
RecipeIngredient class's view
First of all. You are over engineering your domain model. On relational databases Join is bottleneck you should prevent from joins if it doesn't helps you.
public class Recipt
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public ICollection<RecipeIngredient> Ingredients { get; set; }
}
public class IngredientModel
{
public int Id { get; set; }
public string Name { get; set; }
public IngredientUnit UnitType { get; set; } // Unit model is best to be added here. if it doesn't change in a single IngredientModel.
}
public class RecipeIngredient
{
public int Id { get; set; }
public int UnitQuantiy { get; set; } // No need to more classes.
public IngredientModel Model { get; set; }
public Recipt Recipt { get; set; }
}
public Enum IngredientUnitType // Same Unit Model but less database relation as its small finite collection.
{
Killogram,
Count,
....
}
and according to the Microsoft documents its best to use fluentApi configuration for the relations.
Override this method in your Context:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Recipt>.HasMany(P => P.Ingredients).WithOne(P => P.Recipt);
builder.Entity<RecipeIngredient>.HasOne(P => P.Model);
// There is no need to explicit foreign key definition. but you can explicitly define your foreign keys.
}
And for the last part. in Views you can use extra models called ViewModels.
As above domain turned to a minimal domain you just need to pass a list of IngredientModels to your view to complete your View.

Doubts about EF Core 2.1 Relations

I am working on Entity Framework Core Code First approach and ASP.Net Core 2.1 making 3 tables:
Person class
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
Professions' class
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
peopleprofessions' class
public class peopleprofessions
{
[ForeignKey("PersonId ")]
public string PersonId { get; set; }
public ICollection<Person> People { get; set; }
[ForeignKey("ProfessionId")]
public string ProfessionId{ get; set; }
public ICollection<Profession> Professions { get; set; }
}
On my Context:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<peopleprofessions>().HasKey(up => new { up.PersonId, up.ProfessionId });
}
Bearing this in mind:
People can have multiple professions.
The professions table is only for reading stored data like "Accountant".
I have doubts about how I can make table 3 only contain the foreigners and that it can meet the needs that I just mentioned.
I have tried to make the relationship appropriately but I also noticed that in tables 1 and 2 it requests both Id of the table people's professions.
I don't know if I am lost or if I am looking wrong or if there is an alternative to that situation. Thanks for any help you can give me.
You have the use of Collections on the navigation items a bit backwards. For your primary entities (Person and Profession), they should have collections, since it's one-to-many. But for the PeopleProfessions, each record is a single link to a specific entity, so no collection there just a direct object reference.
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class PeopleProfessions
{
public string PersonId { get; set; }
public Person Person { get; set; }
public string ProfessionId { get; set; }
public Profession Profession { get; set; }
}
You can, but don't need to specify a ForeignKey attribute because you are following EFs naming conventions(it will figure it out for you). Your OnModelCreating looks correct for the composite key.
You may want to consider removing the plural from PeopleProfessions (just call the class PeopleProfession) since one instance represents a single People-Profession relationship. I typically do this and but the navigation name in the entities remains plural, since it can represent more than one, i.e.
public ICollection<PeopleProfession> PeopleProfessions { get; set; }

Saving Data using Entity Framework Code First

I am using ASP.NET MVC Razor Entity Framework Code First C#
Class - A
public class Om_Category
{
[Key]
public int CategoryID { get; set; }
public String CategoryName { get; set; }
public String CategorySanitized { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreationDate { get; set; }
}
Class - B
public class Om_CategorySkills
{
[Key]
public Int32 SkillID { get; set; }
public String Skill { get; set; }
public String SkillSanitized { get; set; }
public DateTime CreationDate { get; set; }
public Boolean IsActive { get; set; }
public Om_Category Category { get; set; }
}
When I try to create the record for table Om_CategorySkills. It says
cannot save the duplicate value in Om_Category table.
This is happening because I am sending the Om_Category class object in Om_CategorySkills class object because there are some fields in Om_Category class that are mandatory.
So I am passing the Om_Category class object also in Om_CategorySkills class object. Is there any way to fix this issue ?
Your navigation properties doesn't seem to be right.. Can you try (I didn't test),
public class Om_Category
{
[Key]
public int CategoryID { get; set; }
public String CategoryName { get; set; }
public String CategorySanitized { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreationDate { get; set; }
public virtual Om_CategorySkills CategorySkills{ get; set; }
}
public class Om_CategorySkills
{
[Key]
public Int32 SkillID { get; set; }
public String Skill { get; set; }
public String SkillSanitized { get; set; }
public DateTime CreationDate { get; set; }
public Boolean IsActive { get; set; }
public int CategoryID {get;set;}
public virtual Om_Category Category { get; set; }
}
I see that your Om_CategorySkills object is lacking an Int32 Om_CategoryId property to be used as foreign key. I would also add a virtual modifier to the navigation property Category, in order to allow for lazy loading.
I think that it may be the case that the category object in your new/edited skill is already in the database, but was not the one retrieved by the context, so the context believes you are trying to save a new category with the Id of an existing one.
You should not try to save a skill object with a category object with no changes. Otherwise, the category object should be the one attached to the context.

Store User Date EF MVC4

Am trying to understand problem in how to store every user date like ( comments ,questions,....etc ) ... or when having list of requernmints and we need to store each user checklist of the requirement separately.... i though of the following example :
here an example :
I have list of Questions related to Subject. Then Student will be able to chose subject and view list of the question and answer them.
teacher then can come and see the questions answered for every students in separate view .
How to design the model and the view so that I will be able to store each student Answers!! so teacher can come then and see view students list under his subject and can chose a student to check his answer of the question....
Here my model classes and relations,I don't know the logic of design it .... please guide me!
I hope I explained well
public class Subject
{
[Key]
public int SubjectID { get; set; }
public string SubjectName { get; set; }
public virtual ICollection<Questions> Questions { get; set; } ;
}
public class Teacher
{
[Key]
public int TeacherID { get; set; }
public string TeacherName { get; set; }
public virtual ICollection<Subjects> Subjects { get; set; } ;
}
public class Students
{
[Key]
public int StudentID { get; set; }
public string StudentName { get; set; }
public virtual ICollection<Answer> Answer{ get; set; } ;
}
public class Questions
{
[Key]
public int QuestionsID { get; set; }
public string TheQuestion { get; set; }
public virtual Subject Subject { get; set; }
}
public class Answer
{
[Key]
public int AnswerID { get; set; }
public string TheAnswer { get; set; }
public virtual Subject Subject { get; set; }
}

Mapping a collection of entities in fluent nHibernate

I'm developing a question/answer based application
I have a Post table in the db along the lines of:
ID
Title
Body
DateCreated
AuthorID
AuthorName (in case user not registered)
AutherEmail (as above)
PostType (enum - 1 if question, 2 if reply)
Show (bit field)
Then, there is "PostBase" - which is an abstract class (this has properties common to both Question and Answer - listed below)
I then have an internal "Post" class, which descends from PostBase, and therefore has all the properties listed above.
There is then have a Question class, and an Answer class.
Both use Post as a base class.
Here are the classes:
public abstract class PostBase
{
{
get { return postCreatorEmail; }
//todo: add email address validation here?
set { postCreatorEmail = value; }
} private IList<Attachment> attachments = new List<Attachment>();
public PostBase()
{
//init logic here
}
public virtual DateTime DateCreated { get; set; }
public virtual string ID { get; set; }
public virtual string Body { get; set; }
public virtual DateTime DateLastModified { get; set; }
public virtual string PostCreatorName { get; set; }
public virtual string PostCreatorEmail { get; set; }
public virtual int PostCreatorID { get; set; }
public virtual PostType PostType { get; set; }
public virtual PostSource PostSource { get; set; }
public virtual bool Show { get; set; }
public IEnumerable<Attachment> Attachments { get { return attachments; } }
}
Post
internal class Post : PostBase
{
public virtual List<string> Tags { get; set; }
public virtual string Title { get; set; }
public virtual string ParentPostID { get; set; }
}
Question:
public class Question : PostBase
{
public Question()
{
tags = new List<string>();
}
public string Title { get; set; }
public List<string> Tags { get { return tags; } }
public int NumberOfReplies { get; set; }
}
Answer:
public class Answer : PostBase
{
public string QuestionID { get; set; }
}
I use automapper to map to / from Answer and Post or Question and Post
What I'm trying to do, is create the following class:
public class QuestionWithAnswers
{
public Question Question { get; set; }
public IEnumerable<Answer> Answers { get; set; }
}
Which basically has a "Question" - remember this is just a Post in the db, with a ParentPostID of 0, with a list of Answers (where ParentPostID is equal to Question.ID ... or along those lines)
My question is - how do I map this in fluent nHibernate?
You could use Automapper for QuestionWithAnswers, but Answers has to have an IList and not an IEnumerable:
public class QuestionWithAnswers
{
public virtual Question Question { get; set; }
public virtual IList<Answer> Answers { get; set; }
}
What I don't understand is the existence of QuestionWithAnswers, when the following (I think) should do:
public class Question : PostBase
{
public virtual string Title { get; set; }
public virtual List<string> Tags { get { return tags; } }
public virtual int NumberOfReplies { get; set; }
public virtual IList<Answer> Answers { get; set; }
}
If the question has answers, you'll get them, and if it does not, you don't.