I have existing .net 4 application which is based on object context.
Now I'm adding DbContext in to existing application by inheriting DbContext and call constructor method and pass the existing object context. i.e.
public class DemoModelEntitiesDbContext : DbContext
{
public DemoModelEntitiesDbContext():base(new DemoModelEntities(), dbContextOwnsObjectContext:true)
{
}
public DbSet<ELMAH_Error> ELMAH_Error { get; set; }
}
Than When I call,
using (DemoModelEntitiesDbContext context = new DemoModelEntitiesDbContext())
{
foreach (ELMAH_Error entity in context.ELMAH_Error.ToList())
{
Console.WriteLine(entity.ID);
}
}
I am getting following error message,
"The type 'ObjectContextDemo.ELMAH_Error' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive, nested or generic, and does not inherit from EntityObject."
I checked my existing entities are inheriting from EntityObject.
How to add DbContext in to existing application and not changing existing code?
You could cast to object context but then you gain nothing from DbContext if you 100% stick with existing code. but Ive done that with POCOs, not EntityObjects and can't confirm that it would work with entityobjects.
Otherwise it's not possible to do that without changes. DbContext does not support EntityObject. DbContext is designed for POCOs. Plus there are other code differences between DbContext and ObjectContext. You'd have to change even if you were already using POCOs. If you are using the EF designer, you'd have to start by using a different code gen template (ef5 DbContext template). But that will result in very different classes and plenty of changes to your EF calls in your app.
Related
I am attempting to use EF migrations to build/seed my database but my DbContext is causing an error when I use the update-database command.
The DbContext I have implemented has two constructors: one accepts no arguments and the other accepts an IUserContext interface. The IUserContext interface returns a username as a string. The IUserContext is used in the SaveChanges() method for setting user-related audit fields (ex. CreatedBy, UpdatedBy) common to all of my entities. Depending on the implementation of the IUserContext interface, the username may be retrieved from a HttpContext (in a mvc app), WindowsIdentity (in a console app), etc.
If a user attempts to call SaveChanges on the DbContext and the IUserContext is not set, it throws an exception. Basically, I do not want changes saved in the DbContext if a username cannot be provided by the IUserContext interface for purposes of recording who is making the modifications. If the DbContext is being used just for querying, using the no-args constructor isn't an issue since IUserContext is only used during SaveChanges.
When I attempt to use the update-database command, the DbMigrationsConfiguration is given an instance of the DbContext instantiated using the no-args constructor. Therefore, it throws an exception when it tries to invoke the DbContext's SaveChanges after the Seed() method.
Question: How do I pass an IUserContext to my DbContext so the update-database command will not fail and, more importantly, be able to set the appropriate entity fields to the name of the user seeding the changes? Is there some form of DI or other customization I can perform in the DbMigrationsConfiguration? Should I simply add an IUserContext accessor method to the DbContext so the IUserContext can be set outside of the constructor?
Maybe I should be asking a larger question: What is the best (most generic?) way of relaying user information to a DbContext for the purposes of recording who is making modifications? I gave some thought about moving this logic to the business layer of my application but it seems so convenient to encapsulate it in the SaveChanges of the DbContext (even more so when change tracking is enabled) .
We have a similar situation where we record modified user in SaveChanges() override. What we ended up doing was creating a BaseWrapper and use IoC to fill it. The second part is creating a MigrationsContextFactory that migrations will use to create the context. This class lives in the same folder as our ApplicationDbContext.
using System.Data.Entity.Infrastructure;
namespace MyApp.Data
{
public class MigrationsContextFactory : IDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext Create()
{
return new ApplicationDbContext(new HttpContextBaseWrapper());
}
}
}
public class HttpContextBaseWrapper : IHttpContextBaseWrapper
{
public string UserName
{
get
{
if (HttpContext.Current == null || HttpContext.Current.User == null)
return string.Empty;
return HttpContext.Current.User.Identity.Name;
}
}
}
https://marazt.wordpress.com/2015/01/09/entity-framework-dbcontext-idbcontextfactory-and-codefirst-migration-problem/
New to EF. Following along with DBContext by Lerman/Miller.
When I start a new project, adding EF6 (Database First), the DBContext seems to be added as a default (ie I don't have to add the DBContext separately with T4). Also, for Lazy Loading, the "virtual" needed in the class definitions also seems to be there by default (I don't have to add it like in the book). Is this what is expected?
When you use Database First approach and use EF x DbContext Generator it creates the DbContext for you automatically and set the navigation properties, virtual. If you want to disable lazy loading you can simply use following code
public class MyContext : DbContext
{
public MyContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Most probably the books you are reading are for code first development. If you use database first(especially with the designer) you don't need to make changes.
I'm using Entity Framework 5.0 with code-first approach plus inheritance for my business objects represented by Table Per Hierarchy.
I'd like to have the following structure:
//Assembly 'DataAccess'
public class MyDbContext : DbContext
{
DbSet<AbstractClass> CommonObjects.AbstractClasses { get; set; }
}
//Assembly 'CommonObjects'
public abstract class AbstractClass
{
//implementation
}
//Assembly 'DerivedObjects'
public class DerivedClass : AbstractClass
{
//implementation
}
During runtime, when trying to access the DbContext the first time, the compiler throws an InvalidOperationException saying:
The abstract type 'CommonObjects.AbstractClass' has no mapped descendents
and so cannot be mapped. Either remove 'CommonObjects.AbstractClass' from
the model or add one or more types deriving from
'CommonObjects.AbstractClass' to the model.
Is this scenario even possible? If yes, what am I doing wrong?
Thanks for your answers in advance.
Ben
Additional information:
Maybe I should be a bit more specific:
I got one assembly containing my abstract business objects (only abstractions). The concrete implementations (containing the logic) are kept in the responsible assemblies, as their logic depends upon other classes within that assembly. The issue is, I want to be able to store those conrete implementations in the persistance layer as well. But for that purpose, EF had to know those types in order to enable the mapping. But I dont want to make the persistance layer depend on my business logic layer - only the abstractions.
That's why I tried to add the derived objects to the DbContext directly from the Business Object Layer.
Example:
AbstractClass derivedClass = new DerivedClass();
MyDbContext.AbstractClasses.Add(derivedClass);
But then the exception above is being thrown. I just can't figure out a good structure to achieve this.
As it says on the tin, is it possible to create an instance of a DbContext suitable for use as an Entity Framework 5.0 POCO context where the properies that are normally declared as
public DbSet<T> Entities { get; set; }
aren't set/known until runtime?
I'd like to make a repository that has methods like
public TEntity Find<TEntity>(object key) where TEntity : class
{
return _context.Set<TEntity>().Find(key);
}
public void Update<TEntity>(TEntity entity) where TEntity : class
{
if (_context.Entry(entity).State == EntityState.Detached) //entity is detached
_context.Set<TEntity>().Attach(entity);
_context.Entry(entity).State = EntityState.Modified;
}
.... etc
And then use them like:
Widget w = repository.Find<Widget>(123);
repository.SaveChanges();
This is trivial if the repository's context is set to a class that contains a DbSet<Widget> Widgets, but can it be done such that the entity types that I plan to use won't be know until runtime OR possibly not until I actually USE them? So that if I have a new class Foo, I can immediately query my repository to .Find<Foo>(123) without having to first add a DbSet<Foo> Foos to my DbContext class?
I think this should be possible because there's nothing special about the poco classes or the DbContext instance which holds references to them.
You don't need DbSet<Foo> Foos property in your context. That is just one way to tell context about existence of the Foo entity. There are multiple ways how context discovers mapped entities:
By explicit DbSet<T> properties
By navigation properties in already discovered entities
By specifying mapping in DbModelBuilder
Overriding OnModelCreated in your context type
Creating DbModelBuilder manually, building it and compiling it into DbCompiledModel which can be passed to DbContext constructor
By declaring EntityTypeConfiguration<T> for each entity and adding it to DbModelBuilder (either in OnModelCreated or in manually created DbModelBuilder).
The last option can be used to discover all required entities at application startup (for example by searching assemblies for all entity configuration classes and registering them to model builder) but it is still not fully dynamic solution. Compiled model is normally constructed only once per application run when the context is used for the first time. Without replacing the compiled model you cannot add or remove mapped entity types to the context.
I've created a BLL which queries Entity Framework context. EDML file is in the same BLL assembly. It accepts EF entities as parameters from presentation layer and returns EF entities as results. To accomplish this I kept entities public so presentation layer can create them like DLL.TablName newRecord = new DLL.TableName() etc. The problem is with entities my objectcontext is exposed too since it's public. I can manually change it to private in designer generated code but if I make any changes to it it becomes public again. I didn't see any access modifier setting in the designer. How can I make ObjectContext private or internal?
I'm still in the layer design process so I can change my design if it can't be done.
You could probably inherit your Framework class and using the new keyword "hide" the ObjectContext like so:
public class DataContext : YourEFContext {
private new ObjectContext ObjectContext { get; }
}
I'm pretty sure you wanted something like this...