I'm working on a MVC4/EF5 project and I really want to invest a lot of time in the design of my application.
I have made one policy/principle for myself. My controllers need to be dedicated, which means they can only interact with one specific repo.
E.g. (I'm just writing some pseudo code)
objects: User, Blog, Post, Comment
UserController -> UserRepo -> Handles the User object
BlogController -> BlogRepo -> Handles the Blog object
etc...
Now I'm looking into the following dilemma. What's the most performant to create/add new objects to the database with EF5.
1st Approach:
Add a function to User to add a Blog or add a Post.
addBlog(Blog b){this.Blog.addBlog(b);}
addPost(int blogid, Post p){this.Blog(b).addPost(p);}
For me this means that every post will initiate a usercontroller, inject a userrepo and will have a read operation in the User table to fetch the object. Then it will perform the addPost function and saves the changes.
2nd Approach:
Give the Blog and Post object some foreign key ids
Blog property: UserId
Post property: UserId, BlogId
This means whenever a blog is created, a blogcontroller will be initiated, a blogrepo will be injected and there is no 'LOOKUP' needed. The controller will just add the new Blog object to the context. (the UserId property is set from the websecurity context)
This also means that whenever a post is created, a postcontroller will be initiated, a postrepo will be injected and there is no 'LOOKUP' needed. The controller will just add the new Post object with the injected UserId and BlogId. (which are parameters of the controller action)
For me the second approach seems to devide the load on different tables instead of one. But the downside of this approach is that you can't really do model testing. Because there would be no function addBlog to the User object to be tested.
Is my question somewhat clear? I really want to build the most performant framework for my application. Also what is the impact of a User object with the following properties.
Virtual ICollection
Virtual IColleciton
They can both be retrieved by fetching the User object. (then there is lazy loading on the virtual objects)
Or is it better to let the dedicated BlogController index the blogs that belong to a certain user id.
Thanks a lot for all the advice and comments!
Kr
After investigating the created entity framework statements with SQL Profiler, I came to the conclusion that it doesn't matter how you create a new object.
Adding a new object directly to the repo creates the SAME insert statement as when you add the object through a collection of another object.
public class Blog
{
public int Id { get; set; }
public virtual ICollection Articles { get; set; }
}
public class Article
{
public int Id { get; set; }
}
Related
I want to know what is the best way for designing my domain objects for my project.
The domain objects should be ignorant of the ORM/Framework and even the database technology (MySQL, MSSQL, and even Mongo)
And the next question comes in mind, lets say that i have two objects, Post and Comment.
This is the code for the Post object:
class Post {
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public IList<Comment> Comments { get; set; }
}
Now, my question for the Comment object is should it include a Post Id or just a Post object?
class Comment {
public int Id { get; set; }
public string Content { get; set; }
public Post Post { get; set; }
public int PostId { get; set; } // Should i include it?
}
Is it a good practice to include the Id of the relational object or just its domain object?
Another concern is for no sql database like mongodb.
If i store my data in mongodb, what Post object will the Comment object reference?
In mongodb there is no relationship between post and comments, any post includes list of comments, but the comments themselves are ignorant of the post they are part of.
So what is the best way to make those domain classes compatible both with Sql based database and NoSql databases?
Thank you
Object-oriented design
You designed your Post and Comment classes in a way that they both reference each other. While I'd try to avoid this tight coupling unless absolutely necessary, it surely makes Comment.PostId obsolete, you can just call Post.Id from within a Comment.
Also, your domain objects should probably try to protect their invariants. What you have now is just property bags (even with public setters), and not domain objects, so currently they don't offer any meaningful advantage over the objects you'd use for persistence.
So if you want to create a domain model, ask yourself questions like these:
What can an actor do with a post in the system I'm building?
What data on a comment can an actor retrieve?
Then model your domain objects in a way that supports your business cases. For example, if users of your application are prohibited to change the title of a post, you should remove the setter from Post.Title.
This answer may give you more information on the distinction between domain objects and simple property bags (aka POCOs), even though that answer is in the context of domain-driven design.
Document DB Persistence
To store these objects in a document-oriented DB, you have basically two choices:
Store them as separate documents and reference one from the other
Store comments as part of their post on the post document
Both are valid approaches, you have to decide for your application. Note however that document boundaries are also consistency boundaries, so if you need atomic operations on a post and its comments, your only option is to put them on the same document.
Absolutely you should include it. What if you want to get a list of comments but don't want to get the Post object with each comment, yet still need the PostID?
I have following POCO class being used in EF 6.x.
My question: Why is the navigation property of 'Posts' under 'Blog' entity declared as virtual?
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Tags { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
If you define your navigation property virtual, Entity Framework will at runtime create a new class (dynamic proxy) derived from your class and uses it instead of your original class. This new dynamically created class contains logic to load the navigation property when accessed for the first time. This is referred to as "lazy loading". It enables Entity Framework to avoid loading an entire tree of dependent objects which are not needed from the database.
In some circumstances, it is best to use "Eager Loading" instead, especially if you know that you will be interacting with related objects at some point.
Julie Lerman really is the authority on all things Entity Framework, and she explains this process very well in her MSDN Article Demystifying Entity Framework Strategies: Loading Related Data
Eager loading with Include is useful for scenarios where you know in advance that you want the related data for all of the core data being queried. But remember the two potential downsides. If you have too many Includes or navigation paths, the Entity Framework may generate a poorly performing query. And you should be careful about returning more related data than necessary thanks to the ease of coding with Include.
Lazy loading very conveniently retrieves related data behind the scenes for you in response to code that simply makes mention of that related data. It, too, makes coding simpler, but you should be conscientious about how much interaction it’s causing with the database. You may cause 40 trips to the database when only one or two were necessary.
If you are developing a Web Application where every communication with the server is a new context anyway, Lazy Loading will just create unnecessary overhead to maintain the dynamic class for related objects that will never be loaded. Many people will disable lazy loading in these scenarios. Ultimately, it's still best to evaluate your SQL queries which EF has built and determine which options will perform best for the scenario you are developing under.
I'm a little overwhelmed with all of the information on DDD, unit of work, domain services, app services, etc. I'm trying to figure out how a persistence-ignorant domain model ultimately gets persisted, specifically in the context of unit-of-work and Entity Framework. Let's say I have an Order aggregate root, which I am attempting to keep in my persistence-ignorant domain model (the core of my architectural onion):
public class Order : EntityBase
{
public int Id { get; private set; }
public int MarketplaceId { get; private set; }
public int CustomerId {get; set;}
public List<OrderItem> Items { get; private set; }
public List<OrderComment> Comments { get; private set; }
public void AddItem(OrderItem item) { /**add item**/ }
public void AddComment(OrderComment comment) { /**add comment**/ }
public override bool Validate() { /**validate**/ }
public void Cancel() { /**cancel**/ }
}
Let's say I have a process that updates a property on the Order entity, for example it changes the CustomerId associated with the order.
I have an IOrderRepository in my domain layer, which would have an implementation (in an outer layer) with a function like this:
Order GetOrder(int orderId)
{
//get entity framework order, items, etc.
//map to domain-layer order and return domain-layer order
}
void UpdateOrder(Order order)
{
//get ENTITY FRAMEWORK order, order items, order comments, etc.
//take DOMAIN order (passed in to this function), and update EF items fetched above
//use a single EF unit of work to commit these changes
}
There's something wrong with my approach. The UpdateOrder function seems heavy for a small change; but it also seems I have to do that if my repository isn't aware of which items on the persistence-ignorant domain model have changed. Should I be handling every type of update in a separate repository function? UpdateMarketplace(int marketplaceId), UpdateCustomer(int customerId)?
As I'm typing this, I'm also wondering...maybe the way I have it above is not too heavy? If I change one property, even though I'm doing all of the above, perhaps Entity Framework will recognize that the values being assigned are the same and will only send the one db column update to SQL?
How can I take my Order domain model (fetching is straightforward enough), perform some operation or operations on it that may be limited in scope, and then persist the model using Entity Framework?
You need to look into the Unit of Work pattern. Your UoW keeps track of the changes, so when you get your order from your repository and modify it, you call UnitOfWork.SaveChanges() which should persist all the changes.
Using Entity Framework, your DbContext is basically the Unit of Work but I would create a simpler interface around it so you can abstract it away for easier usage in your higher layers.
Regarding EF, I would recommend mapping your domain entities directly using the code first approach. I would also turn off lazy loading and all the magic stuff so you have full control and less "surprises".
Unfortunately I'm not allowed to share our code but we have all this working pretty effectively with the new EF6 Alpha 3. I would recommend you taking a look at Microsoft Spain's nlayerapp for some implementation examples. I don't agree with many of their design decisions (also, see this review), but I think you can draw some inspiration from the Entity Framework parts. Take a look at their Unit of Work implementation and especially how they have abstracted it away for easier usage in the higher layers, and how they use it in their application services.
I will also recommend looking into creating a generic repository to avoid duplicating lots of logic in your aggregate specific repositories. MS Spain has one here, but you should also take a look at this thread.
Please have a look at this SO question where I gave an example of how I've implemented UoW & Repositories.
As #Tommy Jakobsen told you, your domain entities should be your EF entities, it would avoid you to add a useless mapping layer.
Hope that helps!
You may check ASP.NET Boilerplate's Unit Of Work implementation: http://www.aspnetboilerplate.com/Pages/Documents/Unit-Of-Work
It's open source project, you can check codes. Also, you can directly use it.
I'm trying to implement the repository pattern with ef4 ctp5, I came up with something but I'm no expert in ef so I want to know if what I did is good.
this is my db context
public class Db : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
and the repository: (simplified)
public class Repo<T> : IRepo<T> where T : Entity, new()
{
private readonly DbContext context;
public Repo()
{
context = new Db();
}
public IEnumerable<T> GetAll()
{
return context.Set<T>().AsEnumerable();
}
public long Insert(T o)
{
context.Set<T>().Add(o);
context.SaveChanges();
return o.Id;
}
}
You need to step back and think about what the repository should be doing. A repository is used for retrieving records, adding records, and updating records. The repository you created barely handles the first case, handles the second case but not efficiently, and doesn't at all handle the 3rd case.
Most generic repositories have an interface along the lines of
public interface IRepository<T> where T : class
{
IQueryable<T> Get();
void Add(T item);
void Delete(T item);
void CommitChanges();
}
For retrieving records, you can't just call the whole set with AsEnumerable() because that will load every database record for that table into memory. If you only want Users with the username of username1, you don't need to download every user for the database as that will be a very large database performance hit, and a large client performance hit for no benefit at all.
Instead, as you will see from the interface I posted above, you want to return an IQueryable<T> object. IQuerables allow whatever class that calls the repository to use Linq and add filters to the database query, and once the IQueryable is run, it's completely run on the database, only retrieving the records you want. The database is much better at sorting and filtering data then your systems, so it's best to do as much on the DB as you can.
Now in regards to inserting data, you have the right idea but you don't want to call SaveChanges() immediately. The reason is that it's best to call Savechanges() after all your db operations have been queued. For example, If you want to create a user and his profile in one action, you can't via your method, because each Insert call will cause the data to be inserted into the database then.
Instead what you want is to separate out the Savechanges() call into the CommitChanges method I have above.
This is also needed to handle updating data in your database. In order to change an Entity's data, Entity Framework keeps track of all records it has received and watches them to see if any changes have been made. However, you still have to tell the Entity Framework to send all changed data up to the database. This happenes with the context.SaveChanges() call. Therefore, you need this to be a separate call so you are able to actually update edited data, which your current implementation does not handle.
Edit:
Your comment made me realize another issue that I see. One downfall is that you are creating a data context inside of the repository, and this isn't good. You really should have all (or most) of your created repositories sharing the same instance of your data context.
Entity Framework keeps track of what context an entity is tracked in, and will exception if you attempt to update an entity in one context with another. This can occur in your situation when you start editing entities related to one another. It also means that your SaveChanges() call is not transactional, and each entity is updated/added/deleted in it's own transaction, which can get messy.
My solution to this in my Repositories, is that the DbContext is passed into the repository in the constructor.
I may get voted down for this, but DbContext already is a repository. When you expose your domain models as collection properties of your concrete DbContext, then EF CTP5 creates a repository for you. It presents a collection like interface for access to domain models whilst allowing you to pass queries (as linq, or spec objects) for filtering of results.
If you need an interface, CTP5 doesn't provide one for you. I've wrapped my own around the DBContext and simply exposed the publicly available members from the object. It's an adapter for testability and DI.
I'll comment for clarification if what I said isn't apparently obvious.
In an ASP.NET MVC application where I have the following model..
public class EventViewModel
{
public Guid Id { get; set; }
public List<Guid> Attendants { get; set; }
}
passed to a view...
public ActionResult Create(EventViewModel model)
{
// ...
}
I want to be able to add to the "Attendants" Collection from the View. The code to add it works just fine - but how can I ensure that the View model retains the list? Is there any way to do this without saving/opening/saving etc? I am calling my addition method via jQuery $.load.
public void Insert(Guid attendant)
{
// add the attendant to the attendees list of the model - called via $.load
}
I would also like to add there is no database. There is no storage persistence other than plain files.
If you are posting your data and want to re-display it, you have to round-trip your data back to the view.
To maintain multi-user data integrity, I typically save the data to the database, and then retrieve the data from the database again when passing it back to the view for redisplay.
Potentially, you can do something AJAX-y in the view to add records, so that you don't have to continually round-trip the entire dataset each time a record is added.
EDIT: Just noticed that you don't have a database. If your application is architected properly (i.e. you are using repositories), the method of backend storage shouldn't matter.
For more info on general practices for adding records, see the NerdDinner tutorial.