In Database-First, it is relatively easy to add views into the EDMX. How can we do it in Code-First?
We can create views using Code First in the custom migration class.
public partial class AddNewView : DbMigration
{
public override void Up()
{
Sql("CREATE VIEW [dbo].[NewView] AS ...");
}
public override void Down()
{
Sql("DROP VIEW dbo.[NewView]");
}
}
But how can we access the view in the DbContext?
For tables, we can add domain models into DbContext and do some configuration,
public virtual DbSet<Person> Persons { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new PersonConfiguration());
}
What is the correct way to add the view into DbContext?
It feels a bit hackish but what I end up doing is:
Create a model with all the properties representing your view.
Add the public virtual DbSet<TableName> TableNames { get; } to your DbContext
Run Add-Migration vwTableName
Remove the Up() and Down() methods from the migration.
And add the view creation/deletion SQL scripts:
public override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("CREATE VIEW [dbo].[NewView] AS ...");
}
public override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DROP VIEW dbo.[NewView]");
}
Related
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.
Will using entity framework core code as below erase existing tables in the database that are " not " included part of the DbContext class?
This is all the code i have. No Db initializers. No migrations enabled.
public class EmailServiceDbContext : DbContext
{
public EmailServiceDbContext(DbContextOptions options):base(options)
{
;
}
public DbSet<CourierReportsDeliveriesView> CourierReportsDeliveriesView { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
And the configuration:
// Add DbContext
services.AddDbContext<EmailServiceDbContext>(options => options
.UseSqlServer(Configuration.GetConnectionString("DbConnectionString")));
how can i Add DbSet to my dbContext class, programmatically.
[
public class MyDBContext : DbContext
{
public MyDBContext() : base("MyCon")
{
Database.SetInitializer<MyDBContext>(new CreateDatabaseIfNotExists<MyDBContext>());
}
//Do this part programatically:
public DbSet<Admin> Admins { get; set; }
public DbSet<MyXosh> MyProperty { get; set; }
}
][1]
i want to add my model classes by ((C# Code-DOM)) and of course i did. but now i have problem with creating DbSet properties inside my Context class ...
yes i did!..
this: https://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/
And this: Create Table, Run Time using entity framework Code-First
are solution. no need to dispute with dbSets directly. it just works by do some thing like that:
public class MyDBContext : DbContext
{
public MyDBContext() : base("MyCon")
{
Database.SetInitializer<MyDBContext>(new CreateDatabaseIfNotExists<MyDBContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
var theList = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.Namespace == "FullDynamicWepApp.Data.Domins")
.ToList();
foreach (var item in theList)
{
entityMethod.MakeGenericMethod(item)
.Invoke(modelBuilder, new object[] { });
}
base.OnModelCreating(modelBuilder);
}
}
For those using EF Core that stubble here:
The code below is only for one table with the generic type. If you want more types you can always pass them through the constructor and run a cycle.
public class TableContextGeneric<T> : DbContext where T : class
{
private readonly string _connectionString;
//public virtual DbSet<T> table { get; set; }
public TableContextGeneric(string connectionString)
{
_connectionString = connectionString;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityMethod = typeof(ModelBuilder).GetMethods().First(e => e.Name == "Entity");
//the cycle will be run here
entityMethod?.MakeGenericMethod(typeof(T))
.Invoke(modelBuilder, new object[] { });
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connectionString); // can be anyone
}
}
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?
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