EF6 codefirst slow startup - wpf

I'm in a scenario WPF MVVM EF code first.
All start my application I have to initialize the two databases, but lose 10 seconds each time to do everything. there is a way to speed up?
private void InitDb()
{
var sednaComuniContext = new SednaComuniContext();
sednaComuniContext.Database.Initialize(false);//slowly
if (String.IsNullOrEmpty(Ditta) || Ditta == "BaseDb") return;
var sednaContext = new SednaContext(dbHelper.CreateConnectionString(Ditta));
sednaContext.Database.Initialize(false);//slowly
}
SednaComuniContext:
public class SednaComuniContext : DbContext,IContext
{
public static DatabaseHelper dbHelper;
static string _connection;
public SednaComuniContext()
: base(CreateConnectionString())
{
}
private static string CreateConnectionString()
{
dbHelper = new DatabaseHelper();
return dbHelper.CreateConnectionString("ArchiviComuni");
}
public SednaComuniContext(string connString)
: base(connString)
{
_connection = connString;
if (!Database.Exists())
{
Database.Initialize(true);
}
}
public DbSet<ArticoliFamiglia> ArticoliFamiglia { get; set; }
public DbSet<ArticoliGruppo> ArticoliGruppo { get; set; }
public DbSet<Articoli> Articoli { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SednaComuniContext, Configuration>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
SednaContext:
public class SednaContext : DbContext,IContext //IDbContext
{
public static DatabaseHelper dbHelper;
static string _connection;
public SednaContext()
: base(_connection)
{
}
public SednaContext(string connString)
: base(connString)
{
_connection = connString;
}
public DbSet<ArticoliFamiglia> ArticoliFamiglia { get; set; }
public DbSet<ArticoliFamigliaImpostazioni> ArticoliFamigliaImpostazioni { get; set; }
public DbSet<ArticoliGruppo> ArticoliGruppo { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SednaContext, Configuration>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Can an entity migration be used for that?

Since the Entity Framework team has moved to Entity Framework 6 to the EntityFramework.dll the initial load of the database slowed down considerably, some of these problems were fixed but building a model with 2 entities at a console project takes 4-5 seconds for me as well. See this open item describing part of this problem:
http://entityframework.codeplex.com/workitem/2298
The only workaround for this would be a loading screen where you show the users some fancy progress bar and display terms like loading this and that important part of the application.

Related

Blazor Server App; Refresh in browser a property that is a class comes back nul

App: Blazor Server .NET 5
Using Entity Framework Core
DB; Azure SQL DB
All Ok except for if I refresh the browser, the Helper properties returned by GetActivitys() are null.
Does the Helper property in Activity need a tag?
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Activity> Activitys { get; set; }
public DbSet<Helper> Helpers { get; set; }
}
public class DataAccessService : IDataAccessService
{
private readonly ApplicationDbContext _context;
public DataAccessService(ApplicationDbContext context)
{
_context = context;
}
public async Task<List<Activity>> GetActivitys()
{
var list = await _context.Activitys.ToListAsync<Activity>();
return list;
}
}
public class Activity
{
[Key]
[Column("Id")]
[JsonPropertyName("Id")]
public int Id { get; set; }
[Column("Task")]
[Required]
[JsonPropertyName("Task")]
public string Task { get; set; }
[Column("Helper")]
[JsonPropertyName("Helper")]
public Helper Helper { get; set; }
}
public class Helper
{
[Key]
[Column("Id")]
[JsonPropertyName("Id")]
public int Id { get; set; }
[Column("Name")]
[Required]
[JsonPropertyName("Name")
}
If you want to include navigational properties after materializing your query via .ToListAsync(), you must add a chained method .Include(activity => activity.Helper) before materialization.

asp mvc code first update model without lossing data

I have the following DbContext:
namespace Tasks.Models
{
public class TaskDBInitializer : DropCreateDatabaseIfModelChanges<TasksContext>
{
protected override void Seed(TasksContext context)
{
var projects = new List<Projects>
{
new Projects{ Title="proTitle", Describe="proDescribe" },
};
projects.ForEach(p => context.Projects.Add(p));
context.SaveChanges();
base.Seed(context);;
}
}
public class TasksContext : DbContext
{
public TasksContext() : base("name=TaskDB")
{
Database.SetInitializer(new TaskDBInitializer());
}
public DbSet<Task> Task { get; set; }
public DbSet<Projects> Projects { set; get; }
}
}
I now want to add another model but don't want to lose data that exists within the current database.
How can I add a model to my DbContext without losing data?
Instead of using DropCreateDatabaseIfModelChanges<TContext> as your IDatabaseInitializer<TContext> use MigrateDatabaseToLatestVersion<TContext,TMigrationsConfiguration> which will determine changes within your DbContext then update your existing database to be compatible.
Here is an example of how to implement the MigrateDatabaseToLatestVersion initializer:
namespace Tasks.Models
{
public sealed class TaskDBConfiguration : DbMigrationsConfiguration<TasksContext>
{
public TaskDBConfiguration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
}
protected override void Seed(TasksContext context)
{
var projects = new List<Projects>
{
new Projects { Title = "proTitle", Describe = "proDescribe" },
};
projects.ForEach(p => context.Projects.Add(p));
context.SaveChanges();
base.Seed(context);
}
}
public class TasksContext : DbContext
{
public TasksContext() : base("name=TaskDB")
{
Database.SetInitializer<TasksContext>(
new MigrateDatabaseToLatestVersion<TasksContext, TaskDBConfiguration>()
);
}
public DbSet<Task> Task { get; set; }
public DbSet<Projects> Projects { set; get; }
}
}

Asp.net core Tables for Identity not being created in the database

When I see at other sample projects, the number of tables created for supporting Identity in the db is great (such ones as AspNetRoles, AspNetUserClaims, etc..), but in my case when I make the migration and the update only the User table has been created. What is the reason?
Here is my code in the startup, in the dbcontext and my class user:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSession();
services.AddMemoryCache();
services.AddDbContext<ApplicationDbContext>( options =>
options.UseSqlServer(Configuration["Data:photoarchiver:ConnString"]));
services.AddIdentity<User, IdentityRole > (
opts => {
opts.Password.RequireDigit = false;
opts.Password.RequiredLength = 7;
opts.Password.RequireLowercase = true;
opts.Password.RequireUppercase = false;
opts.Password.RequireNonAlphanumeric = false;
}).AddEntityFrameworkStores<ApplicationDbContext>();
}
Class DbContext:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<User>().HasMany(u => u.Photos).WithOne(i => i.User);
modelBuilder.Entity<Photo>().ToTable("Photos");
modelBuilder.Entity<Photo>().HasOne(i => i.User).WithMany(u => u.Photos);
modelBuilder.Entity<Category>().ToTable("Categories");
}
public DbSet<Photo> Photos { get; set; }
public DbSet<Category> Categories { get; set; }
}
Class User:
public class User : IdentityUser
{
public virtual List<Photo> Photos { get; set; }
[Required]
public string DisplayName { get; set; }
public string Notes { get; set; }
[Required]
public DateTime CreatedDate { get; set; }
}
To get all the AspNetRoles, etc tables "for free" you need to change your ApplicationDbContext to extend from IdentityDbContext<User> instead of just DbContext. IdentityDbContext<T> is found in the Microsoft.AspNetCore.Identity.EntityFrameworkCore namespace. You can see from the source code https://github.com/aspnet/Identity/blob/master/src/EF/IdentityDbContext.cs, IdentityDbContext will bring in the required DbSetproperties.
As you correctly identified in the comment to your question, you will need to call base.OnModelCreating(builder) and re-make your migration files.

CreateDatabaseIfNotExists tries to initialize an existing database

I am using CreateDatabaseIfNotExists when creating a database, but it just doesn't drop the database and then it starts initializing it.
There is my DbContext.
public class AppDbContext : DbContext
{
public AppDbContext() : base("Valtrends")
{
InitializeDbContext();
}
public DbSet<FactorType> FactorTypes { get; set; }
public DbSet<ComplexType> ComplexTypes { get; set; }
public DbSet<Value> Values { get; set; }
public DbSet<DataLoader.Entities.Version> Versions { get; set; }
public DbSet<DefaultPlotData> DefaultPlotData { get; set; }
public DbSet<GraphBucket> GraphBuckets { get; set; }
public DbSet<XfactorFrom> XfactorsFrom { get; set; }
public DbSet<XfactorTo> XfactorsTo { get; set; }
public DbSet<DistributionData> DistributionData { get; set; }
public DbSet<Bin> Bins { get; set; }
public DbSet<DefaultPlotSettings> DefaultPlotSettings { get; set; }
private void InitializeDbContext()
{
Database.SetInitializer(new AppDbInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<FactorType>().HasMany(m => m.CompatibilityListXY).WithMany();
}
}
}
And there is the the first part of my AppDbInitializer.
public class AppDbInitializer : CreateDatabaseIfNotExists<AppDbContext>//DropCreateDatabaseAlways<AppDbContext>
{
public override void InitializeDatabase(AppDbContext context)
{
base.InitializeDatabase(context);
var jsonImporter = new JsonImporter();
List<DataLoader.Entities.Version> versions = (jsonImporter.ImportFromJson<List<DataLoader.Entities.Version>>("Versions.json"));
context.Versions.AddRange(versions);
context.SaveChanges();
After SaveChanges I get a violation of primary keys exception on the entity version.
I am using CreateDatabaseIfNotExists when creating a database, but it just doesn't drop the database and then it starts initializing it
It never drops an existing database. As the name implies, it checks if database exists, and if yes, it does nothing, otherwise it creates and initializes it.
Also note that the InitializeDatabase method of the IDatabaseInitializer is always called, it's the class that implements it responsibility what actual action to perform.
In your case you incorrectly assume that the base method will always create the new database, which is not the case. If you want to add a code that executes only when a new database is created, then you should override the Seed method instead:
public class AppDbInitializer : CreateDatabaseIfNotExists<AppDbContext>
{
protected override void Seed(AppDbContext context)
{
var jsonImporter = new JsonImporter();
List<DataLoader.Entities.Version> versions = (jsonImporter.ImportFromJson<List<DataLoader.Entities.Version>>("Versions.json"));
context.Versions.AddRange(versions);
context.SaveChanges(); // you don't need this, it's automatically called after `Seed` call
}
}

Master/Detail DataGridViews not populating Details DataGridView

I'm using the following technologies: WinForms, Entity Framework 4.4 (5.0 on .NET 4.0), DBContext
I have (what I think is) a very simple Master/Details form, that actually worked just fine before I upgraded from EF 4.0 to EF 4.4. Now, for some reason, the Details DataGridView simply doesn't populate with any data!
Here's my auto-generated schema code:
public partial class RoadMapping
{
public RoadMapping()
{
this.RoadCharacteristics = new HashSet<RoadCharacteristic>();
}
public int RoadMappingID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public virtual ICollection<RoadCharacteristic> RoadCharacteristics { get; set; }
}
public partial class RoadCharacteristic
{
public RoadCharacteristic()
{
}
public int RoadCharacteristicID { get; set; }
public int RoadMappingID { get; set; }
public string Value { get; set; }
public string Description { get; set; }
public virtual RoadMapping RoadMapping { get; set; }
}
Here's my code that was working with EF 4.0:
SATContext = new SafetyAssessmentToolEntities();
dataGridViewMappings.DataSource = bindingSourceMappings;
dataGridViewDetails.DataSource = bindingSourceDetails;
bindingSourceMappings.DataSource = SATContext.RoadMappings;
bindingSourceDetails.DataSource = bindingSourceMappings;
bindingSourceDetails.DataMember = "RoadCharacteristics";
Here's the code that isn't working with EF 4.4:
SATContext = new SafetyAssessmentToolEntities();
SATContext.RoadMappings.Load();
SATContext.RoadCharacteristics.Load();
dataGridViewMappings.DataSource = bindingSourceMappings;
dataGridViewDetails.DataSource = bindingSourceDetails;
bindingSourceMappings.DataSource = SATContext.RoadMappings.Local.ToBindingList();
bindingSourceDetails.DataSource = bindingSourceMappings;
bindingSourceDetails.DataMember = "RoadCharacteristics";
Please note that bindingSourceMappings and bindingSourceDetails are declared by the form designer.
I know there are a lot of more advanced and code-intensive ways to make this work, but I can't understand why this very simple way of doing it won't work anymore.
Any suggestions?
public partial class SafetyAssessmentToolEntities : DbContext
{
public SafetyAssessmentToolEntities()
: base("name=SafetyAssessmentToolEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<RoadCharacteristic> RoadCharacteristics { get; set; }
public DbSet<RoadMapping> RoadMappings { get; set; }
}

Resources