首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Asp.Net核心-如何设定数据种子-未设置为对象实例的对象引用

Asp.Net核心-如何设定数据种子-未设置为对象实例的对象引用
EN

Stack Overflow用户
提问于 2019-06-20 07:28:14
回答 3查看 1.8K关注 0票数 0

在转换所有表以开始使用标识列中的Guid类型后,我未能设定数据种子,因此我简化了大量代码以定位错误,并以一个种子类结束,如下所示:

代码语言:javascript
复制
public class SeedTest
{
    private readonly MyDbContext _context;

    public SeedTest(MyDbContext context)
    {
        _context = context;
    }

    public async Task SeedTest()
    {
        Values value1 = new Values
        {
            Id = Guid.Parse("29c48913-1b5c-47b8-g144-08d6d2273deb"),
            ValueName = "value 1",
            Created = DateTime.Now
        };

        _context.Values.Add(value1);

        await _context.SaveChangesAsync();
    }

    public SeedTest()
    {
    }
}

这个类是从另一个调用的:

代码语言:javascript
复制
public interface IDatabaseInitializer
{
    Task SeedAsync();
}

public class DatabaseInitializer : IDatabaseInitializer
{
    public async Task SeedAsync()
    {
            SeedTest _seedTest = new SeedTest();
            await _seedTest.SeedTest();
    }
}

从startup.cs调用的

代码语言:javascript
复制
    public class Startup
    {
        public IConfiguration Configuration { get; }
        private readonly IHostingEnvironment _hostingEnvironment;

        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            _hostingEnvironment = env;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            ...
            services.AddMyDbContext<MyDbContext>(options =>
                options.UseSqlServer("ConnectionStrings:MyCn"));
            ...
            // DB Seeding
            services.AddTransient<IDatabaseInitializer, DatabaseInitializer>();
            ...
            ...
     }

下面是如何从program.cs触发的

代码语言:javascript
复制
public class Program
{

    public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                var databaseInitializer = services.GetRequiredService<IDatabaseInitializer>();
                databaseInitializer.SeedAsync().Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogCritical(LoggingEvents.INIT_DATABASE, ex, LoggingEvents.INIT_DATABASE.Name);
            }
        }

        host.Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    .Build();
}

不幸的是,这个实现没有在数据库中植入任何数据,我能找到的唯一错误是在日志文件中,它说:

System.NullReferenceException:对象引用未设置为对象的实例。它指向SeedTest类的最后一行。

那么我到底做错了什么呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-06-20 08:07:38

new SeedTest()不初始化其_context字段。您可以在DatabaseInitializer上使用DI来实例化具有MyDbContextSeedTest

代码语言:javascript
复制
public class DatabaseInitializer : IDatabaseInitializer
{
    private readonly MyDbContext _context;

    public DatabaseInitializer(MyDbContext context)
    {
        _context = context;
    }

    public async Task SeedAsync()
    {
        SeedTest _seedTest = new SeedTest(_context);
        await _seedTest.SeedTest();
    }
}
票数 3
EN

Stack Overflow用户

发布于 2019-06-20 08:09:59

您在DatabaseInitialize中显式地创建了一个SeedTest实例,而依赖项注入服务正在创建DatabaseInitialize的实例。在具有正确作用域的服务中注册SeedTest类,并让依赖项注入完成它的工作。

在ConfigureServices中添加如下内容

代码语言:javascript
复制
services.AddTransient<SeedTest>();

修改DatabaseInitializer

代码语言:javascript
复制
public class DatabaseInitializer : IDatabaseInitializer{
     private readonly SeedTest _seedTest;
     public DatabaseInitializer(SeedTest seedTest) 
     {
          _seedTest = seedTest;
     }

     public async Task SeedAsync()
     {
         await _seedTest.SeedTest();
     }
}

删除无参数的SeedTest构造函数,并确保注册的MyDbContext类型是传递给另一个构造函数的类型,因为您同时拥有MyDbContext和DbContext。

票数 1
EN

Stack Overflow用户

发布于 2019-06-20 09:40:09

你可以试试这个,我在这个示例中使用了.net Core2.2-

MyDbContext.cs

代码语言:javascript
复制
public class MyDbContext : DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
        {
            Database.EnsureCreated();
        }

        public DbSet<Values> Values { get; set; }
    }

SeedTest.cs

代码语言:javascript
复制
public class SeedTest
    {
        private readonly MyDbContext _context;

        public SeedTest(MyDbContext context)
        {
            _context = context;
        }

        public async Task SeedTest1()
        {
            Values value1 = new Values
            {
                Id = Guid.Parse("AFE1052A-A694-48AF-AA77-56D2D945DE31"),
                ValueName = "value 1",
                Created = DateTime.Now
            };

            _context.Values.Add(value1);

            var value  = await _context.SaveChangesAsync();
        }

        public SeedTest()
        {
        }
    }

服务

代码语言:javascript
复制
public interface IDatabaseInitializer
    {
        Task SeedAsync();
    }

    public class DatabaseInitializer : IDatabaseInitializer
    {
        private readonly MyDbContext _cotext;

       // Inject DbContext 
        public DatabaseInitializer(MyDbContext dbContext)
        {
            _cotext = dbContext;
        }
        public async Task SeedAsync()
        {
            // Object with contructor which having DbContext parameter
            SeedTest _seedTest = new SeedTest(_cotext);
            await _seedTest.SeedTest1();
        }
    }

startup.cs

代码语言:javascript
复制
 services.AddTransient<IDatabaseInitializer, DatabaseInitializer>();
 services.AddDbContext<MyDbContext>(option=> option.UseSqlServer("Data Source=localhost;Initial Catalog=StackOverFlow1;Integrated Security=True"));

program.cs

代码语言:javascript
复制
public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateWebHostBuilder(args).Build();

            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var databaseInitializer = services.GetRequiredService<IDatabaseInitializer>();
                    databaseInitializer.SeedAsync().Wait();
                }
                catch (Exception ex)
                {
                }
            }
            host.Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

你可以阅读更多关于seed data的内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56677148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档