Can too many navigation properties be too much - c#

If I have an entity:
public class User
{
public int UserId{get;set;}
}
And another entity:
public class Role
{
public int RoleId{get;set}
}
I want to model relation ship via EF Code First so I added:
User.cs
public virtual ICollection<Role> Roles {get;set;}
Role.cs
public virtual User User {get;set;}
This allow me to get user roles like:
context.Users.Roles.ToList();
But User is the main object in database. And it can have relations to 100 tables.
Is adding ICollection<T> and User object best practice or it is not always required (generally is there some rule of thumb for this)?
Sometimes I have feeling that I am creating too large objects and I wonder does this have some performance impact?

You are correct in thinking that dragging in 100 related tables to your dbcontext might not be the most performant solution and ef will drag in all tables that it can see either as a dbset, navigation property, or fluent configuration.
However if you need to navigate from roles to users in your dbcontext and the user entity has navigation properties that point to 100 of tables then your solution would be in this particular dbcontext to tell ef to ignore the tables you're not concerned with something like modelbuilder.ignore('orders') assuming from users you can navigate to orders in some way. in this way you can prune the graph to only consider the entities you need.
You then need another dbcontext for other spheres of interest: the concept is called the bounded context. (Ref Julie Lerman, Eric Evans DDD) You then need to do more work in your app to support multiple db contexts in the same app but it can be done - (See Julie Lerman on enterprise ef) However if you just want one dbcontext in your app where the scope of your model is limited to a subset of tables then the this will work.
I think you can use the ef power tools to view a read only diagram of the tables in your dbcontext model. You can then confirm how well your pruning is going.

Related

Issue with ASP.NET MVC 5 Web Application Entity Framework

I am working on MIT open source license example ASP.NET MVC web applications, and adding them as github public repos, I am also planning to have private github repos for my applications I plan to make money with in the future. I have a developer account with github.com.
I created a BOOKS MVC 5 web application using a TSQL script I was provided during a previous job interview some years ago, and am using GUID for the primary key ID fields with a default value of NEWID(), instead of an INT with IDENTITY, the solution is an ASP.NET MVC 5 web application with database first Entity Framework. I am using LocalDB for my SQL Server with this project, the script to create and populate the database is in my SQL-Server repo and is called BOOKS_Create.sql
I published the solution to my GitHub at the following URL:
https://github.com/ABION-Technology/Books
The TSQL scripts are available in the following repo:
https://github.com/ABION-Technology/SQL-Server
I added links the the shared layout view to show the index view for all Authors in the database, and also links to Index views for the TITLE and SALE EF models.
THe AUTHORS link works just fine, and lists all the authors in the database. But when I click the TITLES link, I get a SQL Exception of 'Author_ID' invalid column name, I did a search through my entire solution and did not find any variable named 'Author_ID' and did not find a C# class with a property called 'Author_ID". So this issue has me very confused there does not appear to be a good way to debug this issue. Thanks.
EF will follow some default conventions to work out FK relationships. The error you are seeing is due to Author having a Titles collection and EF is attempting to automatically set up the 1-to-many between the two. It's expecting to find an "Author_ID" on the Title, which doesn't exist because your schema is set up with a joining table called TitleAuthor.
To resolve this, you will need to map the TitleAuthor entity, in which the Author will contain a collection of TitleAuthors which refer themselves to an Author and Title entity. EF can automatically map joining tables given those tables consist of just the two FKs. As soon as you want to introduce additional fields, then you need to define the joining entity.
public class TitleAuthor
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; internal set;}
public virtual Title Title { get; internal set;}
public virtual Author Author { get; internal set;}
// add other properties as needed..
}
So from your Author entity:
public virtual ICollection<TitleAuthor> Authors {get; internal set;} = new List<TitleAuthor>();
To access the titles for the author:
author.Titles.Select(x => x.Title);
I would recommend reading up on many-to-many mapping with EF. I invariably use deliberate mapping with EF rather than relying on it's conventions. It just helps make it more predictable.
If you are using defaults for PKs then you need to tell EF via the DatabaseGenerated attribute. This isn't needed for read operations, but it will be needed when you go to insert records.
Also, with SQL Server, consider using NewSequentialId() as the default for your UUID PKs. These are more index-friendly than NewId().
The above example using internal (private works too) setters to promote DDD style use of entities. Public setters can lead to misuse/abuse of entities in the sense that the context will diligently attempt to save whatever you set. It's generally a good idea to restrict functionality that would alter an entity's state to a method in the entity with required arguments to be validated, or a repository. I use internal scoping to allow unit tests to still initialize entities. (leveraging InternalsVisibleTo between domain and unit test assemblies)
Reason is you are getting that Author ID error is, you have list of Titles in Author Class. Then there should be relationship between Author and Title entities, which is not exists in your data context. Comment public virtual ICollection<Title> Titles { get; set; } . And it should work.
Reason for you cant search this attribute is, its automatically generated by entity framework. (TableName_PrimaryKey)
If you want to keep this, create relationship in database using foreign keys and add that to your data context also. You may refer this

DDD aggregate and entity framework. Which way is preferable?

I am little bit confused about the problem. I have an entity Product that is represented in the database. It looks like POCO. Here is example (I use attributes instead of fluent api for simplicity).
public class Product
{
[Key]
public int Id { get; set; }
//other properties that have mapping to db
}
But now I want to avoid AnemicDomainModel anti-pattern
So I am going to fill the Product model with methods and properties, that do not have mapping to db, so I should use [Ignore].
public class Product
{
[Key]
public int Id { get; set; }
[Ignore]
public object FooProperty { get; set; }
//other properties that have mapping to db
//other properties and methods that do not have mapping to db
}
I think such a way spoils my model. In this article I've found acceptable workaround. Its idea is to separate Product (domain model) and ProductState (state of product that is stored in the database). So Product is wrapper for ProductState.
I really want to know the views of other developers. Thanks a lot for your answers.
I understood that my real question sounds something like that: "Should I separate Data model and domain model? Can I change EF entities from Anemic to Rich?"
To ensure persistence ignorance of your entities, I've found EF Fluent Mapping to be better than Data Annotations. The mappings are declared in an external file, thus normally your entity doesn't have to change if something in the persistence layer changes. However, there are still some things you can't map with EF.
Vaughn's "backing state object" solution you linked to is nice, but it is an extra layer of indirection which adds a fair amount of complexity to your application. It's a matter of personal taste, but I would use it only in cases when you absolutely need stuff in your entities that cannot be mapped directly because of EF shortcomings. It also plays well with an Event Sourcing approach.
The beauty of the Entity Framework is that it allows you to map your database tables to your domain model using mappings which can be defined using the Fluent API, therefore there is no need to have separate data entities. This is in comparison to its predecessor Linq To SQL where you'd map each table to an individual data entity.
Take the following example, for the paradigm of a Student and Course - a student can take many courses, and a course can have many students, therefore a many-to-many relationship in your database design. This would consist of three tables: Student, Course, StudentToCourse.
The EF will allow you to use Fluent API mappings to create the many collections on either side of the relationship without having the intermediate table (StudentToCourse) defined in your model (StudentToCourse has no existence in a DOMAIN MODEL), you would only need two classes in your domain, Student and Course. Whereas in LinqToSQL you'd have to define all three in your model as data entities and then create mappings between your data entities and domain model resulting in lots of plumbing work open to bugs.
The argument of the anaemic vs rich domain model should have little effect on your mapping between your model and database tables, but focuses on where you place the behaviour - in either the domain model or the service layer.

How To Represent foreign key in Entity Framework's POCO Class

I noticed something when i was reading through some Entity Framework's POCO classes that the one to many relationship is always represented in two ways like following :
1- Public List<User> Users {get;set;}
2- Public Virtual User Users {get;set}
So which one is right and when i should use each, this concept really confused me !!!
I think you've read that wrong. Typically (although not required), you would have navigation properties at both ends of the relationship.
A collection navigation property on the one side (a Department may have a List<User> for example) and a reference navigation property on the many side (a User would have one Department).
It is also recommended that you have a foreign key property as well, for example an int DepartmentId on the User.
You would need to mark the navigation properties as virtual if you wanted to support lazy loading. See here for the requirements on POCO types.

Reducing Repositories to Aggregate Roots

I currently have a repository for just about every table in the database and would like to further align myself with DDD by reducing them to aggregate roots only.
Let’s assume that I have the following tables, User and Phone. Each user might have one or more phones. Without the notion of aggregate root I might do something like this:
//assuming I have the userId in session for example and I want to update a phone number
List<Phone> phones = PhoneRepository.GetPhoneNumberByUserId(userId);
phones[0].Number = “911”;
PhoneRepository.Update(phones[0]);
The concept of aggregate roots is easier to understand on paper than in practice. I will never have phone numbers that do not belong to a User, so would it make sense to do away with the PhoneRepository and incorporate phone related methods into the UserRepository? Assuming the answer is yes, I’m going to rewrite the prior code sample.
Am I allowed to have a method on the UserRepository that returns phone numbers? Or should it always return a reference to a User, and then traverse the relationship through the User to get to the phone numbers:
List<Phone> phones = UserRepository.GetPhoneNumbers(userId);
// Or
User user = UserRepository.GetUserWithPhoneNumbers(userId); //this method will join to Phone
Regardless of which way I acquire the phones, assuming I modified one of them, how do I go about updating them? My limited understanding is that objects under the root should be updated through the root, which would steer me towards choice #1 below. Although this will work perfectly well with Entity Framework, this seems extremely un-descriptive, because reading the code I have no idea what I’m actually updating, even though Entity Framework is keeping tab on changed objects within the graph.
UserRepository.Update(user);
// Or
UserRepository.UpdatePhone(phone);
Lastly, assuming I have several lookup tables that are not really tied to anything, such as CountryCodes, ColorsCodes, SomethingElseCodes. I might use them to populate drop downs or for whatever other reason. Are these standalone repositories? Can they be combined into some sort of logical grouping/repository such as CodesRepository? Or is that against best practices.
You are allowed to have any method you want in your repository :) In both of the cases you mention, it makes sense to return the user with phone list populated. Normally user object would not be fully populated with all the sub information (say all addresses, phone numbers) and we may have different methods for getting the user object populated with different kind of information. This is referred to as lazy loading.
User GetUserDetailsWithPhones()
{
// Populate User along with Phones
}
For updating, in this case, the user is being updated, not the phone number itself. Storage model may store the phones in different table and that way you may think that just the phones are being updated but that is not the case if you think from DDD perspective. As far as readability is concerned, while the line
UserRepository.Update(user)
alone doesn't convey what is being updated, the code above it would make it clear what is being updated. Also it would most likely be part of a front end method call that may signifiy what is being updated.
For the lookup tables, and actually even otherwise, it is useful to have GenericRepository and use that. The custom repository can inherit from the GenericRepository.
public class UserRepository : GenericRepository<User>
{
IEnumerable<User> GetUserByCustomCriteria()
{
}
User GetUserDetailsWithPhones()
{
// Populate User along with Phones
}
User GetUserDetailsWithAllSubInfo()
{
// Populate User along with all sub information e.g. phones, addresses etc.
}
}
Search for Generic Repository Entity Framework and you would fine many nice implementation. Use one of those or write your own.
Your example on the Aggregate Root repository is perfectly fine i.e any entity that cannot reasonably exist without dependency on another shouldn't have its own repository (in your case Phone). Without this consideration you can quickly find yourself with an explosion of Repositories in a 1-1 mapping to db tables.
You should look at using the Unit of Work pattern for data changes rather than the repositories themselves as I think they're causing you some confusion around intent when it comes to persisting changes back to the db. In an EF solution the Unit of Work is essentially an interface wrapper around your EF Context.
With regards to your repository for lookup data we simply create a ReferenceDataRepository that becomes responsible for data that doesn't specifically belong to a domain entity (Countries, Colours etc).
If phone makes no sense w/o user, it's an entity (if You care about it's identity) or value object and should always be modified through user and retrieved/updated together.
Think about aggregate roots as context definers - they draw local contexts but are in global context (Your application) themselves.
If You follow domain driven design, repositories are supposed to be 1:1 per aggregate roots.
No excuses.
I bet these are problems You are facing:
technical difficulties - object relation impedance mismatch. You are struggling with persisting whole object graphs with ease and entity framework kind a fails to help.
domain model is data centric (as opposed to behavior centric). because of that - You lose knowledge about object hierarchy (previously mentioned contexts) and magically everything becomes an aggregate root.
I'm not sure how to fix first problem, but I've noticed that fixing second one fixes first good enough. To understand what I mean with behavior centric, give this paper a try.
P.s. Reducing repository to aggregate root makes no sense.
P.p.s. Avoid "CodeRepositories". That leads to data centric -> procedural code.
P.p.p.s Avoid unit of work pattern. Aggregate roots should define transaction boundaries.
This is an old question, but thought worth posting a simple solution.
EF Context is already giving you both Unit of Work (tracks changes) and Repositories (in-memory reference to stuff from DB). Further abstraction is not mandatory.
Remove the DBSet from your context class, as Phone is not an aggregate root.
Use the 'Phones' navigation property on User instead.
static void updateNumber(int userId, string oldNumber, string newNumber)
static void updateNumber(int userId, string oldNumber, string newNumber)
{
using (MyContext uow = new MyContext()) // Unit of Work
{
DbSet<User> repo = uow.Users; // Repository
User user = repo.Find(userId);
Phone oldPhone = user.Phones.Where(x => x.Number.Trim() == oldNumber).SingleOrDefault();
oldPhone.Number = newNumber;
uow.SaveChanges();
}
}
If a Phone entity only makes sense together with an aggregate root User, then I would also think it makes sense that the operation for adding a new Phone record is the responsibility of the User domain object throught a specific method (DDD behavior) and that could make perfectly sense for several reasons, the immidiate reason is we should check the User object exists since the Phone entity depends on it existence and perhaps keep a transaction lock on it while doing more validation checks to ensure no other process have deleted the root aggregate before we are done validating the operation. In other cases with other kinds of root aggregates you might want to aggregate or calculate some value and persist it on column properties of the root aggregate for more efficient processing by other operations later on. Note though I suggest the User domain object have a method that adds the Phone it doesn't mean it should know about the existence of the database or EF, one of the great feature of EM and Hibernate is that they can track changes made to entity classes transparently and that also means adding of new related entities by their navigation collection properties.
Also if you want to use methods that retrieve all phones regardless of the users owning them you could still though it through the User repository you only need one method returns all users as IQueryable then you can map them to get all user phones and do a refined query with that. So you don't even need a PhoneRepository in this case. Beside I would rather use a class with extensions method for IQueryable that I can use anywhere not just from a Repository class if I wanted to abstract queries behind methods.
Just one caveat for being able to delete Phone entities by only using the domain object and not a Phone repository you need to make sure the UserId is part of the Phone primary key or in other words the primary key of a Phone record is a composite key made up of UserId and some other property (I suggest an auto generated identity) in the Phone entity. This makes sense intuively as the Phone record is "owned" by the User record and it's removal from the User navigation collection would equal its complete removal from the database.

Advice on my ASP.NET MVC, EF layer, and Automapper setup for a project

I'm trying to figure out the best approach to architecting this project. Basically, it's a "band" profile site. I'm using ASP.NET 4, EF, and Automapper (structuremap too, but that's not important). I'm running into performance issues and need advice on whether my approach is right or not (my guess is not). I'll focus on specific sections and provide stripped down examples.
I have a EntityFramework repository class that interacts directly onto the EF objects using LINQ:
[Pluggable("Repository")]
public class EntityDataRepository : IRepository
{
static EntityDataRepository()
{
// other mappings removed
// Data. objects are EF objects, mapping to my DTO classes
Mapper.CreateMap<Data.Event, Models.EventModel>();
Mapper.CreateMap<Data.Genre, Models.GenreModel>();
Mapper.CreateMap<Data.Band, Models.BandModel>();
}
public IEnumerable<BandModel> GetBandsByUser(Guid userId)
{
using (var ctx = new DbContext())
{
var user = GetCurrentUserModel(ctx, userId);
var efBands = from r in user.BandRelations
orderby r.Date
select r.Band;
return Mapper.Map<IEnumerable<Data.Band>, IEnumerable<Models.BandModel>>(efBands);
}
}
}
Bands have genres and events. Note that it maps the EF objects to my DTO object, and returns a list of them. It acts as a proxy to enable my controllers to invoke methods on to obtain the data that it needs (actual logic altered to show what I need):
namespace OpenGrooves.Web.Areas.Edit.Controllers
{
[Authorize]
public class MyBandsController : BaseController
{
public ActionResult ShowBands()
{
IEnumerable<BandModel> bands = repository.GetBandsByUser(loggedUserGuid).First();
return View(bands);
}
}
}
Finally, here's the BandModel class, which is mirroring the Band class entity in EF:
public class BandModel
{
// fluff and scalar properties removed
public IEnumerable<EventModel> Events { get; set; }
public IEnumerable<GenreModel> Genres { get; set; }
}
Basically, am I doing this right? In my EF to DTO classes, the Band EF entity has navigational properties, such as Genres and Events. The problem is, during the mapping that takes place in automapper, these list properties are being populated, especially if one of my proxy methods returns a list of BandModels. It seems to be invoking the Genres and Event EF queries for each record, which is a major performance killer obviously (at least 2 queries for Events and Genres are ran for each BandModel object returned).
Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?
Is there something I need to change in my mappings to enable lazy loading for these navigational properties (events, genres off a BandModel object)?
Thanks!!
Is it OK practice to use EF objects directly in my controllers, possibly even used as models for views?
Yes, Kinda.
This answer is subjective and depends on how you view your separation of concerns. Most MVC developers, including me, swear on view models. It decouples your data or domain classes from the presentation layer. This is awesome.
Some people don't like being awesome, including other languages and frameworks like every PHP MVC framework, Rails, and Django. Nobody can say these languages "do it wrong" but us .NET devs subscribe to a different paradigm.
Your second question is strange you say "is there something to enable lazy loading" right after you say lazy loading is happening. Care to explain?
Lazy loading is on by default in EF4.

Categories