【问题标题】:DbContext not updating databaseDbContext 不更新数据库
【发布时间】:2019-10-14 11:06:23
【问题描述】:

当我保存对 DbContext 的更改时,它不会更新我的数据库。也没有错误。

是的,传入的表单数据已填写。是的,连接字符串是正确的,我知道这一点,因为我能够很好地从数据库中检索数据。如果它具有相关性,则它是多对多关系。

就您而言,路线图就像一篇文章,可以与许多标签相关联。

    public static class RoadmapService
    {
        static ConkerDbEntities dbContext;
        public static void createDbContext(ConkerDbEntities _dbContext)
        {
            dbContext = _dbContext;
        }

        public static void addToDatabase(Form form)
        {
            Roadmaps roadmap = new Roadmaps { RoadmapTitle = form.title, 
                                              RoadmapSummary = form.summary, 
                                              RoadmapBody = form.body };

            var tags = new Tags[form.tags.Length];

            for(int i = 0; i < tags.Length; i++)
            {
                tags[i] = new Tags();
                tags[i].TagId = form.tags[i];
            }

            var roadmapTags = new RoadmapTags[form.tags.Length];

            for(int i = 0; i < tags.Length; i++)
            {
                roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
            }

            dbContext.AddRange(roadmapTags);
            dbContext.SaveChangesAsync();
        }
    }
}

dbcontext创建的地方,这是Startup.cs的构造函数

        public static SearchEngine engine;
        public static ConkerDbEntities dbContext;

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;

            dbContext = new ConkerDbEntities();

            RoadmapService.createDbContext(dbContext);
            engine = new SearchEngine(dbContext);

        }

我没有收到任何错误,也没有任何内容添加到数据库中。我可能在这里做一些根本错误的事情。提前致谢。

【问题讨论】:

    标签: c# .net-core entity-framework-core dbcontext


    【解决方案1】:

    您正在使用异步编程,但您的方法不是异步的。

    当你有异步方法时使用dbContext.SaveChangesAsync();,当不是异步时使用dbContext.SaveChanges();

    此外,您使用的是静态类,如果您使用依赖注入,则不应出现这种情况。 DI 将处理您的对象的生命周期。

    您的类未按应有的定义,您有一些格式错误,应该如下所示:

    public class RoadmapService
    {
        private readonly ConkerDbEntities _dbContext;
    
        public RoadmapService(ConkerDbEntities dbContext)
        {
            _dbContext = dbContext;
        }
    
        public async Task AddToDatabase(Form form)
        {
            Roadmaps roadmap = new Roadmaps {
                RoadmapTitle = form.title, 
                RoadmapSummary = form.summary, 
                RoadmapBody = form.body 
            };
    
            var tags = new Tags[form.tags.Length];
    
            for(int i = 0; i < tags.Length; i++)
            {
                tags[i] = new Tags();
                tags[i].TagId = form.tags[i];
            }
    
            var roadmapTags = new RoadmapTags[form.tags.Length];
    
            for(int i = 0; i < tags.Length; i++)
            {
                roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
            }
    
            _dbContext.AddRange(roadmapTags);
            _dbContext.SaveChangesAsync();
        }
    }
    

    然后在您的控制器中,您可以按原样使用您的服务

    public class OrdersController : Controller
    {
        private readonly RoadmapService _roadmapService;
    
        public OrdersController(RoadmapService roadmapService)
        {
            _roadmapService = roadmapService;
        }
    
        [HttpGet]
        [Route("api/[controller]/{folio}")]
        public async Task<IActionResult> Status(string folio)
        {
            await _roadmapService.AddToDatabase(something);
            return Ok();
        }
    }
    

    我还建议学习 linq 以及如何使用 select avoid those foreach cycles,检查默认的 net core coding standards

    编辑

    我很好奇,在这种情况下 LINQ 会提供任何性能优势吗 vs 只是一个常规的 for 循环?

    更多的是关于您的代码的可读性和可维护性,在答案中我已经放置了一个帖子的链接,其中可以更好地解释,您正在代码中创建technical debt,您正在初始化数组并填充它们,处理指数和更多...,但它减少到这个:

    什么更容易阅读?这个:

    public async Task AddToDatabase(Form form)
    {
        Roadmaps roadmap = new Roadmaps {
            RoadmapTitle = form.title, 
            RoadmapSummary = form.summary, 
            RoadmapBody = form.body 
        };
    
        var tags = new Tags[form.tags.Length];
    
        for(int i = 0; i < tags.Length; i++)
        {
            tags[i] = new Tags();
            tags[i].TagId = form.tags[i];
        }
    
        var roadmapTags = new RoadmapTags[form.tags.Length];
    
        for(int i = 0; i < tags.Length; i++)
        {
            roadmapTags[i] = new RoadmapTags{Roadmap = roadmap, Tag = tags[i]};
        }
    
        _dbContext.AddRange(roadmapTags);
        _dbContext.SaveChangesAsync();
    }
    

    或者这个

        public async Task AddToDatabase(Form form)
        {
            var roadmap = new Roadmap {
                RoadmapTitle = form.title, 
                RoadmapSummary = form.summary, 
                RoadmapBody = form.body 
            };
    
            var roadmapTags = form.Tags
                .Select(tagId => new Tag        // First we take our form.tags and convert it to Tag objects
                {
                    TagId = tagId
                })
                .Select(tag => new RoadmapTags  // Then we take the result of the previous conversion and we 
                {                               // transform again to RoadmapTags, we even could do this in one pass
                    Roadmap = roadmap,          // but this way is more clear what the transformations are
                    Tag = tag
                })
                .ToList();
    
            _dbContext.AddRange(roadmapTags);
            await _dbContext.SaveChangesAsync();
        }
    

    如果您刚开始学习编程,您可以忽略这一点,直到您对forforeachwhile 和其他control structures 更加熟悉。这是结构编程,它本身就是一个话题。

    还有我如何将 roadmapService 对象传递给控制器 构造函数,我只是从未见过。

    这就是依赖注入的神奇之处,让系统为你创建对象,你只需要询问类型。

    这也是一个很大的话题,你应该查看我之前的微软文档链接,但基本上,你所要做的就是将类定义为依赖项,所以,当你要求一个时,系统本身会检查依赖项,以及该对象的依赖关系,直到解决所有依赖关系树。

    有了这个,如果你需要在你的类中增加一个依赖,你可以直接添加,但你不需要修改所有使用该类的类。

    要在控制器中使用它,请check the official docs,您只需将依赖项添加到构造函数中,然后赢!,基本上是两个部分:

    添加到你的 Startup.class

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddTransient<MySpecialClassWithDependencies>();
        ...
    }
    

    然后在你的控制器中:

    public class HomeController : Controller
    {
        private readonly MySpecialClassWithDependencies _mySpecialClassWithDependencies;
    
        public HomeController(MySpecialClassWithDependencies mySpecialClassWithDependencies)
        {
            _mySpecialClassWithDependencies = mySpecialClassWithDependencies;
        }
    
        public IActionResult Index()
        {
            // Now i can use my object here, the framework already initialized for me!
            return View();
        }
    

    【讨论】:

    • 我很好奇,在这种情况下 LINQ 会比普通的 for 循环提供任何性能优势吗?并感谢您提供深入而出色的答案以及忽略我的垃圾代码的意愿。
    • 另外,我如何将 roadmapService 对象传递给 Controller 构造函数,我只是从未见过。
    • @Wasiim-Ouro 添加了一些解释
    • 哇哦,现在的代码非常流畅。我明白了,你现在的意思。非常感谢大佬!!!!!!!!!
    猜你喜欢
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    • 2013-09-22
    相关资源
    最近更新 更多