Entity Framework 7 con database esistente in .Net 5 MVC 6

asp.net-core-mvc c# entity-framework-core

Domanda

Ciao Sto avendo qualche problema a tirare i dati da un database esistente in Utilizzo di Entity Framework 7 MVC 6. (Ho postato il codice del progetto qui ). Ho configurato appsettings.json con la stringa di connessione corretta:

"Data": {
    "DefaultConnection": {
        "ConnectionString": "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
}

Ho il mio contesto personalizzato:

public class DatabaseContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Customer> Customers { get; set; }
}

Due classi Poco:

[Table("Customers")]
public class Customer
{
    [Key]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string EmailAddress { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }
    public User User { get; set; }
    public bool Active { get; set; }
}

[Table("Users")]
public class User
{
    [Key]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string EmailAddress { get; set; }
    public DateTime Created { get; set; }
    public DateTime Updated { get; set; }
    public bool Active { get; set; }
}

E sto configurando il servizio in startup.cs

public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.

        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

        if (env.IsDevelopment())
        {
            // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
            builder.AddUserSecrets();

            // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }

        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<DatabaseContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();

        services.AddMvc();

        // Add application services.

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseApplicationInsightsRequestTelemetry();

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");

            // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
            try
            {
                using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                    .CreateScope())
                {
                    serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                         .Database.Migrate();
                }
            }
            catch { }
        }

        app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseStaticFiles();

        app.UseIdentity();

        // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

    // Entry point for the application.
    public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}

Controller dei miei utenti:

[Route("[controller]")]
public class UsersController : Controller
{
    public DatabaseContext _context { get; set; }

    public UsersController(DatabaseContext context)
    {
        _context = context;
    }
    [Route("[action]")]
    public IActionResult Index()
    {
        using (_context)
        {
            List<User> users = _context.Users.ToList();
        }


        return View();
    }
}

Continuo a ricevere il seguente errore sulla riga Elenco quando navigo alla pagina Utenti / indice:

$ exception {"Riferimento oggetto non impostato su un'istanza di un oggetto."} System.NullReferenceException

Per qualche ragione non sta estraendo le informazioni dal database. Lo creo in Microsoft SQLServer 2014. E ci sono dati nella tabella degli utenti. Mi manca un passaggio o sto tentando di accedere ai dati nel modo sbagliato?

Risposta accettata

Il problema principale può essere risolto con l'uso di

public UsersController([FromServices] DatabaseContext context)
{
    _context = context;
}

invece di

public UsersController(DatabaseContext context)
{
    _context = context;
}

È possibile usare

[FromServices]
public DatabaseContext _context { get; set; }

ma si deve rimuovere il costruttore public UsersController(DatabaseContext context) . L'ultimo modo non è raccomandato, perché RC2 ha abbandonato la seconda strada. Vedi l'annuncio .

Le modifiche sopra riportate risolvono il primo problema che si ha, ma il database ei dati di test che si utilizzano producono un altro problema, poiché il campo Updated delle tabelle Users e Customers contiene valori NULL . Quindi devi usare

public DateTime? Updated { get; set; }

invece di

public DateTime Updated { get; set; }

Il modo in cui ti consiglierei è l'uso del consiglio

dnx ef dbcontext scaffold
    "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
    EntityFramework.MicrosoftSqlServer --outputDir ..\Bestro\Model --verbose

che puoi eseguire nella stessa directory in cui è presente project.json principale (in src\JenSolo ). Ho spostato parti del comando sulla nuova riga per una lettura migliore. Uno dovrebbe mettere tutto in una linea di causa. Il comando precedente creerà le classi Users e Customers invece di [Table("Users")]User e [Table("Customers")]Customer , ma è possibile utilizzare il codice come base e apportare manualmente tutte le modifiche necessarie.

AGGIORNATO: Mi sembra che il seguente comando corrisponda meglio alla generazione delle classi dello scaffold:

dnx ef dbcontext scaffold
    "Data Source=localhost;Initial Catalog=Demo;Integrated Security=True"
    EntityFramework.MicrosoftSqlServer --outputDir ..\Bestro\Model --verbose
    --targetProject Bestro --dataAnnotations

perché si utilizza Libreria di classi Bestro nel progetto principale JenSolo. Dovresti eseguire il comando precedente dalla riga di comando con la cartella ...\src\JenSolo come directory corrente. Creerà la cartella Model nel progetto Libreria di classi (Bestro). La cartella Model conterrà molti file *.cs : un file per ogni tabella di database e un file aggiuntivo DemoContext.cs , che contiene la classe DemoContext derivata da DbContext ( Demo è il nome del database, che si utilizza). È necessario rimuovere la funzione OnConfiguring da DemoContext.cs per poter configurare la stringa di connessione tramite

services.AddEntityFramework()
   .AddSqlServer()
   .AddDbContext<DemoContext>(options =>
      options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

in ConfigureServices di Startup.cs del progetto principale JenSolo .

AGGIORNATO: A partire da .NET Core RC2 si dovrebbe usare lo scaffold dotnet ef dbcontext invece dello scaffold dnx ef dbcontext scaffold .




Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché