I'm trying to get a grasp of using the EF for an upcoming project.
Currently I have this code first code:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
This created the database and tables and I've been able to add blogs / post no problem. But I am confused about how to structure around EF code first approach.
Should both Blog and Post have a reference to BloggingContext and then have their own get / add / update methods ?
Should I create separate BlogManager / PostManager classes that actually do the getting / adding / updating of data and simply return the entity objects?
Should I create separate classes that inherit from Blog / Post that contain the get / add / update methods?
Should both Blog and Post have a reference to BloggingContext
No - the classes themselves should not be tied to a particular source. They should just represent an entity and be independent of where the data comes from. That allows for easier unit testing since you can create a blog that is completely independent of your data source.
Should I create separate BlogManager / PostManager classes that actually do the getting / adding / updating of data and simply return the entity objects?
Yes - this is typically called a repository, so BlogRepository and PostRepository might be better names.
Since the two will be inter-dependent it would also be good to create IBLogRepository and IPostRepository interfaces that the repositories implement so you don't tightly couple the repositories. Then when you query for a blog and want it's post as well the BlogRepository can chain the request to the IPostRepository.
Should I create separate classes that inherit from Blog / Post that contain the get / add / update methods?
No - because inheritance implies an "is a" relationship - and a class that saves a blog it not necessarily a blog itself.
The DbContext class can handle everything data-related on its own. You don't need to include a reference to them in your entity classes (nor should you, since DbContext classes open up a database connection). DbContext will also handle your basic CRUD operations on its own (through the use of the DbSets<T> on it, which are easy ways to access all of the data in a specific table.
If you want, you could also do what #Sergey mentioned above in the comments and implement a repository interface on top of it. I have written a blog post about doing that which you can find here. Basically, you set it up as a generic repository with a background reference to the DbContext class, and in that way you can put up a nice layer in between your application code and your database logic.
Related
I have a good understanding of EF, and generated my database successfully. Now, I am struggling with adding dynamic properties to one of the entity classes. For example, I have a Post class, and other users can make comments to the posts. When I list the existing posts, I want to display the number of comments made to corresponding post.
One solution might be having a property called CommentCount, and updating the Post by increasing the (int) value of the CommentCount property by 1 when a new comment is made.
The other solution, and I think it is a better solution, is that when retrieving the post from the DB, the number of comments associated with the post can be computed and retrieved at the same time and assigned to CommentCount property of the post instance. However, I do not know how to achieve this with EF.
Which approach is highly recommended? Or, is there any other ways of doing this? If it is the second one, how can I achieve this with EF?
1) You should simply consider not putting the property called CommentCount into your model. When you develop for example a WPF Windows application, you should consider using MVVM pattern and the CommentCount would belong to your ViewModel class and not to your Model class. There you implement INotifyPropertyChanged and you can use it from your frontend Views. Analogically there is MVC pattern for ASP.NET etc.
There are other design patterns like Repository pattern. Using this pattern you can create the CommentCount in your repository class and not in your
model class. This would be similar to your second solution.
2) I assume from your question that you are using code-first approach:
generated my database successfully
If you do so and you wish to include CommentCount directly in your Model class, you can do it this by adding partial class file to your project like this:
namespace DBModel.Models
{
public partial class Post
{
public int CommentsCount
{
get { return this.Comments.Count; }
}
...
But I cannot see why to create extra property in your model just for that.
On the other hand adding this field as a computed field into your SQL database could make sense and then it would be part of your EF model.
If you calculation is very complex you should try creating a View in your DB and then add it to your Model?
But if your Model have something simple like
class Post {
public int postid { get; set; }
public virtual ICollection<comment> comment { get; set; }
}
In your controller you can do
db.post(x => x.postid == yourid).comments.count()
to get total of comment
or in your view
#foreach (var item in Model)
{
<li>item.postid;</li>
<li>item.comment.Count();</li>
}
Or update your class
class Post {
public int postid { get; set; }
public virtual ICollection<comment> comment { get; set; }
public int CommentCount
{
get
{
return comment.Count();
}
}
}
Just remember bring related data in your query.
In my case POI have properties parish_id, sector_id, city_id and parish have municipality, and municipality have state.
Using this query I can get Poi with all the related data.
filter = db.poi
.Include("parish")
.Include("sector")
.Include("city")
.Include("parish.municipality")
.Include("parish.municipality.state")
.Where(x => x.sector_id == SectorID);
I'm confused on how I'm going to updated related entities using DDD. Let say I have a Employee Class and Workschedule Class. How should I updated a specific workschedule of a certain employee? The relationship between Employee and Workschedule is One-To-Many. Below is the code I'm using how to Add/Update a certain workschedule.
public class Employee
{
public int EmployeeId { get; set; }
public virtual ICollection<WorkSchedule> WorkSchedules { get; set; }
public WorkSchedule AddWorkSchedule(WorkSchedule workSchedule)
{
this.WorkSchedules.Add(workSchedule);
return workSchedule;
}
public WorkSchedule EditWorkSchedule(WorkSchedule workSchedule)
{
var originalWorkSchedule = this.WorkSchedules.FirstOrDefault(w => w.WorkscheduleId == workSchedule.WorkscheduleId);
originalWorkSchedule.ClockIn = workSchedule.ClockIn;
originalWorkSchedule.ClockOut = workSchedule.ClockOut;
return originalWorkSchedule;
}
}
public class WorkSchedule
{
public int WorkScheduleId { get; set; }
public DateTime ClockIn { get; set; }
public DateTime ClockOut { get; set; }
public int EmployeeId { get; set; }
}
Is this correct? Did I follow DDD correctly? Also, my thinking right now Workschedule is a value object but I'm putting and ID for normalization purposes
your Model should be "POCO" class
CRUD methods such.. Add or Edit will be considored as part of "Service" or "Repository"
here is a quick idea that just came to my mind / how should it look like and its usage..
IRepository repository { get; set; } //implement Interface and inject via IoC Container
//..usage
var employee = repository.GetEmployee(123); //get by id
//..new WorkSchedule
employee.WorkSchedules.Add(workSchedule);
var result = repository.Save(employee);
Since everything here is EF related, it isn't much of DDD. IF the code works as desired, then it's ok. But DDD has no relationship to EF or any other ORM. You should design the Domain objects, without caring at all about the database or an ORM. Then, in the repository you map the Domain entities to Persistence entities which will be handled by the ORM.
Also, my thinking right now Workschedule is a value object but I'm putting and ID for normalization purposes
This is the consequence when the layers and models are mixed. You don't need an ID in the domain but you need an id for persistence. Trying to fit both requirements in one model and calling that model Domain leads to nowhere.
EF it is not for DDD, it is too clumsy. EF is for same codemonkeys who likes t map SQL tables to Entities and do it like ActiveRecord antipatter, but after more intelligent developers started to call this as a bad practice, they started to use ORM, entities and continue monkeycoding.
I'm struggling with EF last 3 years to let it work DDD way. It successfully resists and wins. Without hacks it doesn't work.
The on-to-many relations still doesn't work as expected, there is not way to create entities with constructor, not the public properties and so on.
Need a little help please if anyone can shed some light on this.
I've created a code-first MVC 3 application which I have working fine. I'm refactoring now to remove as much coupling as possible as I want the domain model to be used in various other MVC 3 applications later on. What I have now is a collection of entities which are persisted via a normalised database and they are CRUD-ed through a repository pattern. I have used Ninject to DI the repositories via the controller's constructor and am using models within the MVC 3 project to act as DAOs.
So, within the domain I have an entity called Case that has a foreign key to another case Client that looks like this:
public class Case : ICase
{
[Key]
public int CaseId { get; set; }
public string CaseName { get; set; }
public DateTime DateCreated { get; set; }
public IClient Client { get; set; }
}
Then I have an interface (the interface exists mainly to implement it to the view model to add my data annotations - I know I could add the annotations to the domain object but as I said I want to use this domain model in other applications which will have a different ubiquitious language.
public interface ICase
{
int CaseId { get; set; }
string CaseName { get; set; }
DateTime DateCreated { get; set; }
IClient Client { get; set; }
}
And then I have my view model within the MVC 3 project.
public class CaseModel : ICase
{
[HiddenInput(DisplayValue = false)]
int CaseId { get; set; }
[Required(AllowEmptyStrings = false)]
[MaxLength(100)]
string CaseName { get; set; }
[RegularExpression("")]
DateTime DateCreated { get; set; }
IClient Client { get; set; }
}
So, my first problem is this: changing my foreign key reference for Client to IClient is a new thing, and it returns a null object. When the type was a concrete class it returned fine - I assume this is because EF4.1 tries to create an instance of IClient. Am I totally wrong here or is there a way around this?
My second problem (which may negate my first problem) is am I also doing something wrong by adding data annotations to a view model inheriting the interface of my domain entity? Should I be using model meta data? If so, how do I use meta data in such a way that I can make the data annotations unique to each project without touching the domain?
Thanks!
Caveat: I'm not an expert on EF or MVC3.
We're in the process of building EF Code First entities, and we're not planning on adding interfaces to the entities. Repositories get interfaces. Units of Work get interfaces. Entities don't. Repositories return concrete entities, which are POCOs. Entities may be coupled to related entities. Models and other classes will typically get repository interfaces and/or unit of work interfaces injected in. For testing, we'll just new up some POCO entities and return them from the mock repositories.
We're planning to make the relevant POCO properties virtual so that EF can create proxies.
If you want to decouple a view from concrete entities, I'd first ask what value you expect to gain from that. Is the view going to be reused with different entities? If so, one option would be to use something like AutoMapper to copy the properties over. You'd have to be aware of the immediate access of lazy-load properties, though.
First off, I think this is somewhat ridiculous to do but the other members of my team insist upon it and I can't come up with a good argument against it other than "I think it's dumb"...
What we're trying to do is create a completely abstract data layer and then have various implementations of that data layer. Simple enough, right? Enter Entity Framework 4.1...
Our end goal here is that the programmers (I do my best to stay only on the data layer) never want to have to be exposed to the concrete classes. They only ever want to have to use interfaces in their code, aside from obviously needing to instantiate the factory.
I want to achieve something like the following:
First we have our "Common" library of all of the interfaces, we'll call it "Common.Data":
public interface IEntity
{
int ID { get; set; }
}
public interface IUser : IEntity
{
int AccountID { get; set; }
string Username { get; set; }
string EmailAddress { get; set; }
IAccount Account { get; set; }
}
public interface IAccount : IEntity
{
string FirstName { get; set; }
string LastName { get; set; }
DbSet<IUser> Users { get; set; } // OR IDbSet<IUser> OR [IDbSet implementation]?
}
public interface IEntityFactory
{
DbSet<IUser> Users { get; }
DbSet<IAccount> Accounts { get; }
}
From that we then have an implementation library, we'll call it "Something.Data.Imp":
internal class User : IUser
{
public int ID { get; set; }
public string Username { get; set; }
public string EmailAddress { get; set; }
public IAccount Account { get; set; }
public class Configuration : EntityTypeConfiguration<User>
{
public Configuration() : base()
{
...
}
}
}
internal class Account : IAccount
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DbSet<IUser> Users { get; set; } // OR IDbSet<IUser> OR [IDbSet implementation]?
public class Configuration : EntityTypeConfiguration<Account>
{
public Configuration() : base()
{
...
}
}
}
Factory:
public class ImplEntityFactory : IEntityFactory
{
private ImplEntityFactory(string connectionString)
{
this.dataContext = new MyEfDbContext(connectionString);
}
private MyEfDbContext dataContext;
public static ImplEntityFactory Instance(string connectionString)
{
if(ImplEntityFactory._instance == null)
ImplEntityFactory._instance = new ImplEntityFactory(connectionString);
return ImplEntityFactory._instance;
}
private static ImplEntityFactory _instance;
public DbSet<IUser> Users // OR IDbSet<IUser> OR [IDbSet implementation]?
{
get { return dataContext.Users; }
}
public DbSet<IAccount> Accounts // OR IDbSet<IUser> OR [IDbSet implementation]?
{
get { return dataContext.Accounts; }
}
}
Context:
public class MyEfDataContext : DbContext
{
public MyEfDataContext(string connectionString)
: base(connectionString)
{
Database.SetInitializer<MyEfDataContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new User.Configuration());
modelBuilder.Configurations.Add(new Account.Configuration());
base.OnModelCreating(modelBuilder);
}
public DbSet<User> Users { get; set; }
public DbSet<Account> Accounts { get; set; }
}
Then the front-end programmers would be using it such as:
public class UsingIt
{
public static void Main(string[] args)
{
IEntityFactory factory = new ImplEntityFactory("SQLConnectionString");
IUser user = factory.Users.Find(5);
IAccount usersAccount = user.Account;
IAccount account = factory.Accounts.Find(3);
Console.Write(account.Users.Count());
}
}
So that's pretty much it... I'm hoping someone on here might be able to either point me in the right direction or help me out with a good argument that I can fire back at the development team. I've looked at some other articles on this site about EF not being able to work with interfaces and one reply saying that you can't implement IDbSet (which I find kind of curious, why would they provide it if you couldn't implement it?) but so far to no avail.
Thanks in advance for any help!
J
The first argument is that EF doesn't work with interfaces. DbSet must be defined with a real entity implementation.
The second argument is that your entities should not contain DbSet - that is context related class and your entities should be pure of such dependency unless you are going to implement Active record pattern. Even in such case you will definitely not have access to DbSet of different entity in another entity. Even if you wrap set you are still too close to EF and entity never have property accessing all entities of another entity type (not only those related to current instance).
Just to make it clear DbSet in EF has very special meaning - it is not a collection. It is entry point to database (for example each LINQ query on DbSet hits database) and it is in normal scenarios not exposed on entities.
The third argument is that you are using a single context per application - you have a single private instance per singleton factory. Unless you are doing some single run batch application it is definitely wrong.
The last argument is simply practical. You are paid for delivering features not for wasting time on abstraction which doesn't give you (and your customer) any business value. It is not about proving why you should not create this abstraction. It is about proving why you should do it. What value will you get from using it? If your colleagues are not able to come with arguments which have business value you can simply go to your product manager and let him use his power - he holds the budget.
Generally abstraction is part of well designed object oriented application - that is correct. BUT:
Every abstraction will make your application somehow more complex and it will increase cost and time of development
Not every abstraction will make your application better or more maintainable - too much abstraction has reverse effect
Abstracting EF is hard. Saying that you will abstract data access in the way that you can replace it with another implementation is task for data access gurus. First of all you must have very good experience with many data access technologies to be able to define such abstraction which will work with all of them (and in the end you can only tell that your abstraction works with technologies you thought about when you design that). Your abstraction will work only with EF DbContext API and with nothing else because it is not an abstraction. If you want to build universal abstraction you should start studying Repository pattern, Unit of Work pattern and Specification pattern - but that is a big deal of work to make them and to implement them universal. The first step needed is to hide everything related to data access behind that abstraction - including LINQ!
Abstracting data access to support multiple APIs make sense only if you need it now. If you only think that it can be useful in future than it is in business driven projects completely wrong decision and developer who came with that idea is not competent to make business targeting decisions.
When it make sense to do "a lot of" abstraction?
You have such requirement now - that moves burden of such decision to person responsible for budget / project scope / requirements etc.
You need abstraction now to simplify design or solve some a problem
You are doing open source or hobby project and you are not driven by business needs but by purity and quality of your project
You are working on platform (long living retail product which will live for a long time) or public framework - this generally returns to the first point because this type of products usually have such abstraction as requirement
If you are working only targeted application (mostly single purpose applications on demand or outsourced solutions) the abstraction should be used only if necessary. These applications are driven by costs - the target is delivering working solution for minimal costs and in the shortest time. This target must be achieved even if resulting application will not be very good internally - the only thing which matters is if application meets requirements. Any abstraction based on "what if ... happens" or "perhaps we will need ..." increases costs by virtual (non existing) requirements which will in 99% never happen and in most cases initial contract with customer didn't count which such additional costs.
Btw. this type of applications is targeted by MS APIs and designer strategy - MS will make a lot of designers and code generators which will create non optimal but cheap and quick solutions which can be created by people with smaller skill set and are very cheap. The last example is LightSwitch.
I have looked at two of Microsoft's tutorials for MVC. In one tutorial they are creating a .edmx file to handle the Entity Framework in order to execute Linq queries. In another tutorial they made a class called "MusicStoreEntities.cs" here is the code:
using System.Data.Entity;
namespace MvcMusicStore.Models
{
public class MusicStoreEntities : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Cart> Carts { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
}
}
And the tutorial creates an instance of this class and starts doing Linq queries as well. What are the differences between these 2 methods? and how can I make DbSet objects in a .edmx file? Thank you.
There are various ways to create your model structure.
You can code POCO classes first, and create the database manually.
You can code POCO classes first, and create the database automatically using code first libraries.
You can create your database schema, and import it into a class diagram (which will supply all the models and navigation).
You can create your class diagram, and create your database schema from that.
1 and 2 create only the cs, while 3 and 4 create the edmx.
You can check this for Code First EF (this includes the DbSet part of your question).
EDIT: You can even use POCO classes with an existing database, as posted here.