for classes that evolve quickly in terms of dependencies with plenty of ForeignKeys in new classes that are being created iteration after iteration during the development process, is there a way to tell EntityFramework to load all the dependencies you find for a given object by Id assuming that there are other objects in new tables with that reference as a ForeignKey?
Basically what I want to avoid is changing the way of loading the object adding the relevant Include every time I have a new dependency.
Related
I have three projects (WCF projects, not clients), I have one database for all, now how will I use EF with this? should I make a fourth project which will have the db context and the entities and then add a reference to it in all three projects? or should I just have a separate context for each project and just add the tables i need for each project? some of the table are really used everywhere. so what's the best solution for this?
Another question: should I expose the EF db context in the separate project so other projects can access it? something like:
MySeparateProject myPr = new MySeparateProject();
using (var db = new myPr.DBContext())
{
// do stuff with entities
db.SaveChanges();
}
I think the cleanest thing to do is create a data access project (class library) that contains just your models and db context, and reference that from all of your other projects.
Some people will say that you should make one class library with just the models, and then have yet another that has the DbContext, and the have repository classes, and then.... I feel this is overkill for the majority of projects. Having the models and context in one place just makes it really easy to keep all the dependent projects consistently in sync when it comes to data access.
Here's a typical project structure for me:
Here, Squelch.Data contains all of my models and db contexts, Squelch.Core contains core business logic, and my two "applications" (Squelch.Portal ad CdrImport), and the various test cases, all reference these base class libraries.
I would create a separate data access project. It is good practice to separate your data layer out anyhow. Depending on the nature of the project and how you want to test it, you may want to take a look at something like the repository pattern (though there is debate about its value with EF).
http://msdn.microsoft.com/en-us/library/ff649690.aspx
I am working on a project using EF5 and am lost when it comes to adding a second DbContext to the project. I have created the DbContext but my migrations do not work. How do I make sure that my second DbContext (totally separate database) is set up and I can start updating the database?
Doing a "Enable-Migration" fails because a Configuration file/class already exists for my previous DbContext.
You should split your data access libraries into separate projects. This way you can treat each one separately, and they have no danger of conflicting with each other (so long as you call them something different). I would also suggest making sure they are in unique namespaces.
My application is broken down into several assemblies.
The MyProject.Infrastructure assembly contains all of the Domain objects such as Person and Sale as well as interfaces repositories such as IPersonRepository and ISaleRepository.
The MyProject.Data assembly contains concrete implementations of these repositories.
The repositories pull data from a database and instantiate new domain classes. For example, IPersonRepository.GetPersonByNumber(customerNumber) will read a customer from the data source, create a new Person class, populate it and return to the caller.
I'm now starting to see cases where adding some methods to my Domain classes might make sense, such as Person.UpdateAddress(address).
Is it ok to put this method on my Person class as a virtual method, and then create derived classes inside my Data layer which override those methods to provide the desired functionality?
I want to make sure I'm not going breaking any DDD conventions.
I know I also have the option of putting these methods on the repository - e.g. IPersonRepository.UpdatePersonAddress(person, address).
Person.UpdateAddress should definitely be in your domain, not in your Repository. UpdateAddress is logic and you should try to avoid logic inside your repository. If you're working with Entity framework there is no need for 'data classes'.
Most ORMs have change trackers which will persist related entities automatically when you persist the main one (provided you declared the right relations in the mapping configuration), so you don't need UpdatePersonAddress() on your Repository. Just do whatever you want to do at the object level in Person.UpdateAddress(address) without thinking about persistence, this is not the place for that.
What you need though is an object that will be called in execution context-aware code to flush changes to the persistent store when you think it's time to save these changes. It might be a Unit of Work that contains the Entity Framework DbContext, for instance.
My database model (sometimes referred to as "context") is dynamically assembled at startup based on which services and/or plugins are installed. Plugins and services export their model definition fragments through my IoC container and the application core picks them up and runs them when the DbContext.OnModelCreating method is called.
The question is: Can I (and how do I) use Code First Migrations with this setup?
(below is more information on what I've tried and what particular problems are)
In my previous project, the database was inherited from some old code so we couldn't use any of the Code First database generation stuff anyway. We simply kept a long line of delta scripts and executed them manually on deploy (it was a single-host kind of project).
Now I'm starting a new project, and this time, the database is brand new, ready for Code First to play with. Initially, I was all excited about Code First Migrations, seemed like the way to go. Until I actually tried it. The initial attempt, quite obviously, failed due to the absence of an explicitly defined DbContext in my project.
So far, it looks like the only viable option is to manually code migrations, with which I am perfectly fine. However, it turns out that this is not as simple as just creating a few classes inherited from DbMigration.
After some experimentation on a small test project, I was able to find out that the migration autogenerator adds an implementation of IMigrationMetadata, which, among other things, contains a hash of my model as the values of the Source and Target properties. Presumably, this hash is then used to identify a path across migrations from the "current" state of the database (as recorded in the __MigrationHistory table) to the newest state as defined by the model in code. This totally makes sense, but...
Naturally, I have no idea where to get that hash for my model, which makes me unable to implement IMigrationMetadata on my migrations.
On the other hand, I see that the metadata interface is not included in the DbMigration class itself, which makes me think that it might be optional. It then follows that migrations can actually work without the hash values, but the question is - how?
All the information I could find on the internet is just simple, very basic tutorials. No information on how to create migrations manually (and whether it's even supported). No documentation on how it actually works and how to extend it. And it is not quite obvious from outside.
I am ready to resort to ILSpy at this point, but the whole EF is so complex that I fear I may not be able to find what I need in reasonable time.
Here are a few ideas that you could pull together to find a solution that works for you. I realize I mentioned some of these in our other thread, but I'm including them here for others reading this question.
Automatic migrations allow Code First to automatically calculate and apply changes to the database.
You can write your own code to generate and apply migrations. I've written a post about applying migrations and the MigrationsScaffolder class will help you create migrations.
When you run the project , an extra table is created in the database.
EdmMetadata table
The hash is always created with the help of EdmMetadata Entity and the current code first model. It is SHA-256 hash stored in the EdmMetadata table of the database. You can get it from that table.
Methodology to be followed will be:
Get the hash of the current model using
var hash=GetModelHash(OldContext);
Check whether the model in the code (new model) is compatible with the model in database(old model) using
CompatibleWithModel(hash,CurrentContext,ObjectContext)
This method returns bool.
If it is not compatible, then delete the existing tables in the database.
Create new tables
Save the current hash to the databse
Seed the data.
The code may look like:
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var modelHash = GetModelHash(objectContext);
if (CompatibleWithModel(modelHash, context, objectContext))
return;
DeleteExistingTables(objectContext);
CreateTables(objectContext);
SaveModelHashToDatabase(context, modelHash, objectContext);
SeedData(context);
}
Be sure to make the class inherited from
IDatabaseInitializer<T> where T:DbContext
I have a code first model that I'm using in a project. But now I have other projects that are going to use the same model. Of course, I don't want to duplicate the model in all projects so the idea is to encapsulate the model in a separate assembly. So far so good, until you also want to "enhance " the model for some project like adding a ctor with some specific paramaters.
Using partial classes doesn't work as it needs to be part of the same assembly. Using inheritance doesn't really work either as entities of the model has ICollection to other entities, so how to make this work ? Am i going in the right direction ?
Not sure I'm very clear, so please be patient ;-)
If you need to have shared model, you really need to place it in separate assembly and this assembly must contain everything you need in all projects. So if you need additional constructor you must add that constructor to the shared assembly. If you don't want to affect other projects dependent on that assembly you must increment the version of the shared assembly (and use strong name).