Entity Framework affecting my domain - c#

I have been using NHibernate on a system for sometime and I am quite happy with how it works, but I thought I would have a go at switching NHibernate out and putting in Entity Framework purely for a learning exercise. However there is a problem I have come across though, in my domain I have 2 classes (somewhat simplified for examples)
public class Post
{
public Post()
{
Comments = new List<Comment>();
}
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Text { get; set; }
public virtual DateTime DatePosted { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Comment
{
public virtual int Id { get; set; }
public virtual string CommentText { get; set; }
public virtual Post Post { get; set; }
}
The mappings for this work fine when I am using NHibernate, I can quite happily traverse between my Post Comment one to many relationship, Comments are lazy loaded as expected and all is good.
But when moving to EntityFramework it seems in order for the relationship to work, I need to change my Comment class to include PostId field as well as the Post object in order to get the relationship as such.
public class Comment
{
public virtual int Id { get; set; }
public virtual string CommentText { get; set; }
public virtual int PostId { get; set; } // added in for entityframework
public virtual Post Post { get; set; }
public virtual int UserId { get; set; }
}
With this field added into my domain object the mappings now seem to work, but I feel slightly uneasy about this as it feels like Entityframework if forcing me to change my domain, and I was under the impression that the domain model should know nothing of the persistence layer.
So do I really need this extra PostId field added in to my Comment class to get the relationship to work or am I doing something wrong?
Am I just being to pedantic about the domain being affected by the change in persistence layer?
Doesn't having the Post and PostId fields together like this mean that if say you change PostId, you will also have to handle the change to update Post field or vice versa in the Comment class?
Thanks
CD

In my opinion, this is one of the major deficiencies of Entity Framework. You can get EF to work without adding the foreign key, however your application will have to retrieve the entity from the database in order to set the property because EF does not have the equivalent of NHibernate's ISession.Load method.

Related

How many model classes should I have entity? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I have an Article entity in my database:
public class Article
{
public Guid Id { get; set; }
public string Heading { get; set; }
public string Author { get; set; }
public string Content { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public int ViewsCount { get; set; }
public ImageData Image { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
For the creation I have ArticleInputModel, and for displaying the details view, I have ArticleDetailsModel, and for update I have ArticleUpdateModel (etc....)
However those models have the same properties.
Should I separate this much if it means repetitions of code?
I try to follow SRP but this seems like is breaking DRY principle?
Am I overlooking something and what?
Should I separate this much if it means repetitions of code?
Usually, you can identify three situations with potentially different sets of properties when working with model classes (Data Transfer Objects; DTOs) for a single entity:
entity creation
entity reading (displaying, viewing)
entity updating
However, there may be many more subtypes — e.g. different ways to create or update an entity, partial vs. full update, various kinds of displays, e.g. full view, some kind of partial views, view of an entity in a list etc.
It does make sense to have a system in constructing DTOs, such that you differentiate between the create, read (view), update DTOs in respect to your Create, Read, Update operations. You can see a clear parallel between such DTOs and CRU(D) operations (there's typically no DTO for the Delete operation).
Regardless of the particular naming you use, such categorizations help future maintainability of your code: if, in the future, you need to introduce a property that may not be set during entity creation, but can be altered during an update, or vice versa, it is easy to do without extensive changes to unrelated parts of code, e.g. you change the updating path only, but avoid changing the creating path.
I try to follow SRP but this seems like is breaking DRY principle?
Providing the model (DTOs) classes are semantically different, then I don't see this as a violation of DRY. However, this may be subjective.
Think of DTOs as secondary objects. The primary declaration is the database entity, which is part of your data model. The various views of such an entity in the form of DTOs are dependent on this entity declaration. As long as you keep it to a simple public SomeType PropName { get; set; } in the DTOs, it is not a violation of DRY you couldn't live with. In addition, it makes sense to e.g. keep comments explaining various properties in entity declarations only, and not duplicate them into DTOs (unless you have to generate some API docs, but that's solvable with <inheritdoc/> as well). What's important, is the clear distinction between entities and DTOs and their roles.
If you're creating a new instance of an Article, what is it's Id?
Or as a more clear example, what will it's UpdatedOn date be?
How do you update something that doesn't exist yet?
One other issue you might come across very quickly is how are you going to return a list of all the articles by a particular Author?
In the Article table you should be storing Author as an Id linking as a foreign key to the Author table (assuming there can only be a single Author).
If your article table now looks like this...
public class Article
{
public Guid Id { get; set; }
public string Heading { get; set; }
public Id Author { get; set; }
public string Content { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public int ViewsCount { get; set; }
public ImageData Image { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
...you might begin to see where separate ViewModels/DTOs come into play.
Create
public class CreateArticle
{
public string Heading { get; set; }
public IEnumerable { get; set; }
public string Content { get; set; }
public string Image { get; set; }
}
You're creating a new Article so will probably be inserting an auto generated Guid as the key. You'll also be fairly likely to be taking the current date/time as the CreatedOn date. Author would come from a lookup list of some description so you'd need to pass some sort of list into the View (simplified as IEnumerable above). The image is most likely going to be supplied from a path to the image location so you'd maybe want to display as a text box.
Add
public class AddArticle
{
public string Heading { get; set; }
public Id Author { get; set; }
public string Content { get; set; }
public ImageData Image { get; set; }
}
When you've filled in your Create form, you now want to add it to the db. In this case your DTO needs to add data in the format the db expects. So you'd now be passing the selected Author Id and maybe the ImageData after some processing magic elsewhere.
You still don't need an Article Id or CreatedOn as these will be added once this DTO has validated.
Details and View
Hopefully you're now seeing the slight differences that make the ViewModel a valuable asset. You might also require something like the following to show the details of an Article as opposed to viewing the Article itself:
public class DetailOfArticle
{
public Guid Id { get; set; }
public string Heading { get; set; }
public Author Author { get; set; }
public string Content { get; set; }
public string CreatedOn { get; set; }
public string UpdatedOn { get; set; }
public int ViewsCount { get; set; }
}
public class ViewArticle
{
public Guid Id { get; set; }
public string Heading { get; set; }
public string Author { get; set; }
public string Content { get; set; }
public string CreatedOn { get; set; }
public string UpdatedOn { get; set; }
public int ViewsCount { get; set; }
public ImageData Image { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
Notice that the details might pass in an Author entity so that you can supply more information (this could also be exploded out into separate properties). You might also want to pass the date (and/or time) as a string after formatting etc.
The Article detail probably wouldn't need the comments as it's essentially the meta-data about the Article whereas the Article view is the Article as you'd want to present it for reading.

Clarification of one-to-many navigation properties in Entity Framework

I'm a bit confused by conflicting examples of one-to-many model relationships using EF that I'm seeing online.
One video I watched setup a relationship between tables like so:
public class CustomerType
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public int CustomerTypeId { get; set; }
public CustomerType CustomerType { get; set; }
}
So a Customer can only have one CustomerType, but a CustomerType can be used by many Customers. This code works fine, I can fetch a Customer's CustomerType with LINQ using Include.
Now I'm looking at another resource showing the same kind of relationship:
public partial class Standard
{
public int StandardId { get; set; }
public string StandardName { get; set; }
public virtual ICollection<Teacher> Teachers { get; set; }
}
public partial class Teacher
{
public int TeacherId { get; set; }
public string TeacherName { get; set; }
public Nullable<int> StandardId { get; set; }
public virtual Standard Standard { get; set; }
}
This looks almost the same, except:
In this example, the Standard class (equivalent to my CustomerType) has a navigation property back to a collection of Teachers, which my first example does not have. Is this just convenient to have if I want to get a list of all teachers for a given standard, or is it necessary to properly set up the relationship?
The properties in the second example are marked virtual and the first are not -- it seems that best practice is to make nav properties virtual, but is there a reason you wouldn't want to do that?
If it matters, I'm using MVC5 and EF6 and I just want to know if one example is right and one is wrong, or just two styles of getting to the same place.
Thanks!
The navigational properties are to make queries easier for the programmer. Your examples are basically the same with the difference that in Standard you can access Teachers through query while in CustomerType you can not access Customers with this CustomerType because you do not have it as a navigational property. Nevertheless, you can always include List<Customer> Customers in Customer Type.
Also it is better to add virtual to your navigational property for the sake of lazy loading.
MSDN
It depends on your needs, if you will never have to get the navigation property and just need a foreign key for sake of data integrity then you can simply add an integer and mark it as a foreign key. ex: instead of having a CustomerType instance, you can simply have a CustomerTypeId and that is it.
As for the virtual keyword, you can add it if you want to have a lazy loading enabled in your DBContext, cause EF generates proxy classes that inherits from your model classes and it overrides the virtual properties to add the needed logic to lazy load the navigation properties.
If you have a lazy loading disabled, then no need to mark any property as virtual

Implementation of navigational properties for described data model

INTRODUCTION
I am trying to learn how to use Entity framework on my own ( Code First approach ) by solving a small task that I have designed myself.
In order to understand my problem, you must be familiar with the content of the task I mentioned, so i will provide relevant information in the below section.
RELEVANT INFORMATION:
I have invented the following data model for a small quiz:
Each player answers 10 questions.
Each question has 3 possible answers, user chooses one (by clicking on the radio button, for example)
Only one answer is correct, other 2 are wrong.
PROBLEM:
I got stuck at implementing POCOs, so I need your advice on how to implement them properly.
I believe I did the basic stuff properly and that my main problem is in implementing navigational properties.
MY EFFORTS TO SOLVE THIS:
I do not have much to show. Still, my habit is to always show everything I have, in order to ease the task of the community.
Therefore, these are my unfinished POCOs:
public class Answer
{
public int AnswerId { get; set; }
public string TextOfTheAnswer { get; set; }
}
public class Question
{
public int QuestionId { get; set; }
public string TextOfTheQuestion { get; set; }
}
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
}
During writing of this post, I am using Google to learn as much as possible to solve my problem. If I make any headway I will update this post accordingly.
QUESTIONS:
How should I implement navigational properties to mirror the relationships from my data model?
Additionally, is there a way for me to enforce some of the imposed restrictions ( each question has 3 options; player answers on 10 different questions; only one answer is correct answer to the question; and so on...)?
I apologize if these questions may sound trivial to someone experienced. I am just beginning with C# and Entity framework, and can not wait to write anything that works. I hope you can all relate. Thank you for your understanding.
As for the navigational properties, here's something to get you started (let me know if there's something I have missed):
public class Answer
{
[Key]
public int AnswerId { get; set; }
public string TextOfTheAnswer { get; set; }
public int QuestionId{get;set;}
[ForeignKey(nameof(QuestionId))]
public virtual Question Question{get;set;}
}
public class Question
{
[Key]
public int QuestionId { get; set; }
public string TextOfTheQuestion { get; set; }
public virtual ICollection<Answer> Answers{get;set;}
public int CorrectAnswerId{get;set;}
[ForeignKey(nameof(CorrectAnswerId))]
public virtual Answer CorrectAnswer{get;set;}
}
public class SessionQuestion
{
[Key]
public int SessionQuestionId { get; set; }
public int QuestionId{get;set;}
[ForeignKey(nameof(QuestionId))]
public virtual Question Question{get;set;}
public int PlayerAnswerId{get;set;}
[ForeignKey(nameof(PlayerAnswerId))]
public virtual Answer PlayerAnswer{get;set;}
public int TriviaSessionId { get; set; }
[ForeignKey(nameof(TriviaSessionId))]
public virtual TriviaSession TriviaSession{ get; set; }
}
public class TriviaSession
{
[Key]
public int SessionId { get; set; }
public int PlayerId { get; set; }
[ForeignKey(nameof(PlayerId))]
public virtual Player Player{ get; set; }
public virtual ICollection<SessionQuestion> SessionQuestions{get;set;}
}
public class Player
{
[Key]
public int PlayerId { get; set; }
public string Name { get; set; }
public virtual ICollection<TriviaSession> TriviaSessions{get;set;}
}
Basically, EF creates subclasses of your classes at runtime, so leaving the navigation properties virtual lets the EF classes override them and obtain the reference according to the key which resides in the property whose name is the string passed to the ForeignKey attribute's constructor (quite a mouthful, huh?).
One to many navigation is easily created via declaring a virtual generic ICollection property.
Note that this model enforces the fact that only one question is correct- by design. As for the other restrictions, it sounds like business logic rules, not something you should have your data layer enforce.

How do I use EF to automatically create a database and repository in ASP.NET MVC?

I have started to learn ASP.NET MVC, and at this time of studying I wanna create simple blog site. I have decided to use ASP.NET MVC and ORM Entity Framework. Probably you have some useful links about this theme?
I tried to start from creating Model code first.
i have 3 classes Post, User(User can be admin), Comments.
Please I need help to make the relations between the database models. I have code like this right now:
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Comment> Comments { get; set; }
public DateTime PublishDate { get; set; }
}
public class User
{
public readonly bool IsAdmin { get; set; }
public string FirstName { get; set; }
public string SecondName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public DateTime DateOfBirthday { get; set; }
public string Country { get; set; }
public string City { get; set; }
public List<Post> Posts { get; set; }
public List<Comment> Comments { get; set; }
}
public class Comment
{
public int CommentId { get; set; }
public string UserName { get; set; }
public string Content { get; set; }
public DateTime PublishDate { get; set; }
}
These are my classes to create database tables, but I'm not sure how make relations like many-to-one.
Is it correct to make List of Comments for Post or just write int CommentID?? I have never use database very deep, just saw a few lessons. Can somebody to advise how make repository or correct my Model code?
Thank you very much!
There are plenty of good tutorials out there about how to do this. This one, for example:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
To answer some of your questions, yes, the name CommentId is correct; every EF class that you want stored in the database must have either a field called Id or a field called MyClassId (where "MyClass" is the name of your class). I've found that the latter makes your life easier, especially when doing joins.
Unless you have some relationships that EF can't figure out automatically, you don't have to specify the relationships yourself: EF will automatically detect the correct relationship for you. I don't see anything in your code that EF can't handle automatically.
One thing you will have to do is make the List<Post> and List<Comment> fields virtual; that way EF can supply database-backed relationships.
Good luck.
I enjoyed the Building an MVC 3 App with Code First and Entity Framework 4.1
tutorial. Includes a video that I found very easy to follow.

EF code first automatic foreign key association problem

I've got a basic grip of the latest version of EF code first via this tutorial - http://www.asp.net/mvc/tutorials/getting-started-with-mvc3-part4-cs but I'm slightly confused about one aspect and wondering if anybody could shed light on it? To explain - there's a class called "Site" which I want to have a field called "HomePageId" which should then map to the "SitePage" object with that Id. Seems simple enough? But when EF creates the Db and the relationships it doesn't seem to understand this. I'm sure it's something I'm doing wrong - here's the code:
public class Site
{
public int SiteId { get; set; }
public string SiteName { get; set; }
public string SiteUrlPortion { get; set; }
// Relationship - SitePages
public virtual ICollection<SitePage> SitePages { get; set; }
// Relationship - HomePage
public int HomePageId { get; set; }
public virtual SitePage HomePage { get; set; }
}
public class SitePage
{
public int SitePageId { get; set; }
public string SitePageTitle { get; set; }
public string SitePageUrlPortion { get; set; }
// Relationship - Site
public int SiteId { get; set; }
public virtual Site Site { get; set; }
}
The "SitePage" class generates the relationship back to "Site" as you would expect. But what I've got in terms of columns in both tables not only doesn't make sense but the relationship from the code-side of things doesn't work as expected. (Eg when I give the "Site" a "HomePageId" the site's "HomePage" is null.
Obviously there's little out there in terms of documentation because this is still in development, but just wondering if anybody had any ideas? Do I need to start decorating the properties with Attributes? Or am I asking it to understand something that it never will?!
Thanks to all in advance. I'll persevere anyway and post back anything I find obviously.
Rob
try marking your HomePage property with a ForeignKey attribute like this
[Foreignkey("HomePageId")]
public virtual SitePage HomePage { get; set; }
you could also use the fluent configuration but don't remember that offhand
It is probably a limitation in EF. That EF can only handle one relationship between 2 tables.
You have 2 relationships between the tables, to the list of site pages and to the home page.
try removing this line:
public virtual SitePage HomePage { get; set; }
You still have the homepageid, so in a way this information was redundant.

Categories

Resources