I have a question about inheriting a custom DbContext class.
I have created a custom DbContext class called BaseContext in namespace 1 using C# Ado.net entity model generator as shown here:
namespace NS1
{
public partial class BaseContext: DbContext
{
public BaseContext(): base("name=BaseContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<PLAYERS> PLAYERS { get; set; }
}
}
And in the other namespace, I have created another context which uses the same database but its some other tables.
namespace NS2
{
public partial class ExtensionContext: DbContext
{
public ExtensionContext(): base("name=ExtensionContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<CRICKET_PLAYERS> CRICKET_PLAYERS { get; set; }
}
}
Now I am in a situation to use PLAYERS DbSet in the ExtensionContext. I have tried to inherit the BaseContext from ExtensionContext and pass the ExtensionContext connection string to the BaseContext constructor which in turn sends to the DbContext.
But during implementation I get an exception stating
The PLAYERS name does not exist in the current ExtensionContext
Please give me some insight into the possibility of reusing the existing DbSet types in the extended context.
Thanks in advance
Related
I want to try to share a class (es. user) from two dbcontext.
The idea is 1st dbcontext has all method to work with user (add/remove/update/etc) the 2nd dbcontext only need to access (read the user data).
To do that I have created a class abstract Users and I add this class to the db context, so the problem is when create the migration for the 1st dbcontext and the 2nd.
In my 1st I want to track the changes on my POCO user class in the second I don't want to track/create the table.
I try to use Ingore on OnModelCreating but in this way the code first not create the migration but dbcontext don't have the correct model creating and I'm not able to do operation to table db (i use this approch suggested on EF Data Pints
--Update--
[Table("User")]
public abstract class BaseUser {
[Key]
public virtual int Id {get;set;}
public virtual string Name {get;set;}
}
//DB context 1
public class OUser : BaseUser{
}
public class oneDbContext : DbContext
{
public virtual IDbSet<OUser> OneUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
....
}
//DB context 2
public class MUser : BaseUser{
}
public class twoDbContext : DbContext
{
public virtual IDbSet<MUser> TwoUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Ignore<MUser>();
}
So now if I call the code first with Add-Migration whith modelBuider.Ingore the table User not appear in the script but when I try to access to table via db context I catch the error
The entity type Muser is not part of the model for the current context.
But if I uncomment the ingore the access to table work fine but model try to add the table User.
I'm thinking to use ExceptionLogger or ExceptionFilterAttribute in my Web API 2.x application. My OR/M is Entity Framework 6 and AutoFac as my IoC.
Consider exception attribute below:
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
public IDbContext MyContext { get; set; }
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
// some code
MyContext.SaveChanges();
}
}
I think, if my app throws any exception OnException method will be invoke and I need a new instance of DbContext to save the error log, but my AutoFac configuration for DbContext is InstancePerRequest so I think AutoFac will resolve MyContext as a shared DbContext.
Here is my AutoFac configuration for DbContext:
builder.RegisterType<DbContext>()
.As<IDbContext>()
.InstancePerRequest();
How could I make AutoFac to reslove DbContext as a new instance for ApiExceptionFilterAttribute?
Ok, since no one answered my question, I talk a little about how everyone could solve this problem. To solve this problem you can only use ServiceLocator pattern (it's an anti-pattern.). By injecting a life-time-scope object of AutoFac you are able to create different scopes.
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
// public IDbContext MyContext { get; set; }
public readonly ILifetimeScope LifeTimeScpoe{ get; set; }
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
// some code
using(var scope = LifeTimeScope.BeginLifeTimeScope("ExceptionLogging"))
{
using(var dbContext = scope.Resolve<>(IDbContext))
{
// do some log logic
dbContext.SaveChanges();
}
}
}
}
I have two databases that so happen to have the same table name. Entity is giving me an InvalidOperationException stating "The entity types 'PmsUser' and 'AcctUser' cannot share table 'NGUSERS'...
I created these using a code first approach.
My models for both look something like
[Table("NGUSERS")]
public partial class AcctUser
{
...
and
[Table("NGUSERS")]
public partial class PmsUser
{
...
They each have their own respective connection string to differing databases. What do I need to do to get it to allow the same table name (modifying the Database isn't an option)?
Use two ModelBuilder instead of attributes. Then pass the created DbModel to the DbConnection. Or set the database name in the DbContext. See Entity Framework Connections and Models.
This base class helps to register the model builders with the DbContext:
public abstract class ModelBuilderBase {
protected readonly DbModelBuilder ModelBuilder;
protected ModelBuilderBase(DbModelBuilder modelBuilder) {
ModelBuilder = modelBuilder;
}
public abstract void BuildModel();
}
ModelBuilder implementation:
public class ModelBuilder1 : ModelBuilderBase {
public ModelBuilder1 (DbModelBuilder modelBuilder) : base(modelBuilder)
{ }
public override void BuildModel() {
ModelBuilder.Entity<AcctUser>().ToTable("NGUSERS");
}
}
DbContext:
public class DbContext1 : DbContext {
public DbContext1() : base("Database1") /* set DB name */ {
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
var modelBuilders = new List<ModelBuilderBase> {
new ModelBuilder1(modelBuilder)
};
modelBuilders.ToList().ForEach(x => x.BuildModel());
}
}
Create ModelBuilder2 and DbContext2 for the second DB/Table.
I'm using an assembly (dll) that contain my Context class, this class holds both the identity tables and my own tables:
namespace SharedModels
{
public class ApplicationDbContext : Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext();
public DbSet<UserTask> Tasks { get; set; }
public static ApplicationDbContext Create();
protected override void OnModelCreating(DbModelBuilder modelBuilder);
}
}
I can't change the code in it, but I need to set an entity (from Tasks table) to modified, but I can't find the Entry method on that context:
apparently it doesn't inherit from DBContext class, is there a way to accomplish this?
It turns out that I should add a reference to: Microsoft.AspNet.Identity.EntityFramework;
I couldn't find this without distrusting the Intellisense:
Using EF6, .NET 4.0
I have my own custom models and am using Database First approach. I've modified the edmx to use the same namespace as my custom models. I'm getting the error in the subject of the thread when running the code. The class 'User' does exist in my model and in my edmx. I also have my custom DbContext like so:
public class MyEntities : DbContext
{
public MyEntities()
: base("Name=MyEntities")
{
User = Set<User>();
}
public virtual DbSet<User> User { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}
Any ideas?