• 用Entities Framework实现代码优先和依赖注入所遇到的问题总结


    最近在搞毕业设计,底层到EF来实现与数据库的连接。由于是第一次用EF来做项目,遇到了种种特别奇怪的出错。

    现在,总结自己所遇到的问题,方便以后避免。

    第一就是要引用两个包:

    用Nuget包引入:Moq和Ninject 

    以上两个包用于实现依赖注入。

    第二EFDbContext里的实体要和数据库里的表致,不然就会出现,EFDbContext修改了数据库的数据,而数据库里的数据却没有被修改,总之就是要匹配。

    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Data.Entity;
     6 using System.Data.Objects;
     7 using System.Data;
     8 
     9 namespace DAL.Entities
    10 {
    11     public class EFDbContext : DbContext
    12     {
    13         public DbSet<Account> Account { get; set; }
    14         public DbSet<Address> Address { get; set; }
    15         public DbSet<Book> Book { get; set; }
    16         public DbSet<BookCart> BookCart { get; set; }
    17         public DbSet<Cart> Cart { get; set; }
    18         public DbSet<Category> Category { get; set; }
    19         public DbSet<City> City { get; set; }
    20         public DbSet<Menu> Menu { get; set; }
    21         public DbSet<Orders> Orders { get; set; }
    22         public DbSet<Province> Province { get; set; }
    23     }
    24 }

    特别是注意一点:就是表名会在其类名上加上字符“s”,我也还没有找出是什么原因。所以加上就不会报错。

    对应的数据库如下图:

    最后就是配置一点要写对:

     <add name="EFDbContext" connectionString="Data Source=.;Initial Catalog=BookStore;Integrated Security=True" providerName="System.Data.SqlClient" />

    第五步:更改数据模型

    随着我们应用程序开发的推进,我们将继续改进和重构我们的模型。EF 代码优先类库包括一些很好的开发功能,这使我们在开发数据库时更容易协调某些改进。

    给Dinner(餐会)模型添加一个新的属性

    让我们对我们的Dinner类做一个简单的修改,更具体的说,我们将给Dinner类添加一个新的“Country”属性。

    做完改动,让我们在Virtual Studio中按下F5按钮,重新编译并运行应用程序。将会看到下面的这些错误信息:

    这些错误信息之所以出现,是因为我们修改了Dinner类的结构定义,我们的模型对象现在已经不再和数据库中自动创建的Dinners表一致了。

    当EF自动地为你创建数据库时,默认地会增加一个“EdmMetadata”表,这个表用来记录自动创建数据库时使用的模型对象的形状。

    当EF发现你修改过模型对象,并且和之前自动创建的数据库不再同步时,就会出现上面的错误消息。

    也有可能就是在系统表里多出一个表格,应该是系统生成的:

    所以如果出现这样的问题,就先到数据库看下是不是多了表。

    重新同步数据模型类到数据库

    我们有很多同步模型对像和数据库的方式:

    • 我们可以手动地更新数据库中的结构(Schema)让它们保持一致。
    • 我们也可以先删除数据库文件,然后重新运行应用程序,让EF自动重新创建数据库。
    • 我们也可以开启EF 代码优先功能,当数据模型发生任何改变时能够自动更新数据库 。

    下面,让我们在NerdDinner应用程序中看看如何使用最后一种的自动更新的方式。

    当模型对象发生变化时重新创建数据库(RecreateDatabaseIfModelChanges)功能

    在EF 代码优先类库的CTP 4版本中包括了一个非常有用的开发时development-time)功能,它允许你在任意时刻修改数据模型类,自动重建数据库。当你开启这项功能的时候,EF能够识别用来创建数据库的类模型在何时被改动,何时可以重建你的数据库以匹配新的模型类——你不需要做任何手工操作。

    这项功能在你刚开发一个应用程序时特别实用,因为它为你快速地重构你的模型代码带来了很大的自由度和灵活性——你根本不用去手动地保持数据库结构的同步。它特别适合SQL CE,因为SQL CE是一个基于文件的数据库而且可以随时在运行时删除和创建。这使得开发流程变得不可思议的流畅。

    启用这项功能最简单的方法就是在Global.asax类中的Application_Start()事件处理函数中加上Database.SetInitializer()方法的调用。

    这个调用告诉EF当数据模型发生任何变化时,重建NerdDinners.sdf数据库以匹配NerdDinners类。现在当我们重新运行应用程序的时候,再也不会出现提示说类模型和数据库不匹配的错误信息了。反而,EF会自动重建数据库以匹配新的数据模型类,我们的应用程序会正常运行:

    防止表名生成带“s”

    创建一个名为 DAL 的文件夹,在这个文件夹中创建名为 SchoolContext 的类,使用下面的代码替换原有的代码。

    复制代码
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using ContosoUniversity.Models;
    using System.Data.Entity.ModelConfiguration.Conventions;
    namespace ContosoUniversity.Models
    {
    public class SchoolContext
    : DbContext
    {
    public DbSet<Student> Students { get; set; }
    public DbSet<Enrollment> Enrollments { get; set; }
    public DbSet<Course> Courses { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
    }
    }
    复制代码

    这段代码使用 DbSet 类型的属性定义每一个实体集。在 EF 术语中,一个实体集典型地关联到一个数据库中的表,一个实体关联到表中的一行。

    在 OnModelCreating 方法中的代码防止数据库中的表名被多元化。如果没有这样处理的话,生成的表将会被命名为 Students,Courses 和 Enrollments。现在,表名将会被命名为 Student,Course 和 Enrollment。开发者可以决定表名是否被多元化。这个教程使用单数模式,但是重要的是你可以这行代码来选择喜欢的模式。

    第三写下依赖注入的实现过程

    首先要扩展下控制器

    代码如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Ninject;
    using Moq;
    using System.Web.Routing;
    using System.Web.Mvc;
    using DAL.Concrete.Framework;
    using DAL.Entities;
    using IBLL.Framework;
    using BLL.Framework;
    
    
    
    namespace BookStoreUI.Infrastructure
    {
        public class NinjectControllerFactory : DefaultControllerFactory
        {
            private IKernel ninjectKernel;
    
            public NinjectControllerFactory()
            {
                ninjectKernel = new StandardKernel();
    
                AddBindins();
    
            }
    
            protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
            {
                return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
            }
    
            //绑定数据
            private void AddBindins()
            {
                //Mock<IProductRepository> mock = new Mock<IProductRepository>();
    
                //mock.Setup(h => h.Products).Returns(
                //    new List<Product> { 
                //    new Product{Name="FootBall",Price=25 },
                //    new Product{Name="Surf Board",Price=179},
                //    new Product{Name="Running shoes" ,Price=95}              
                //    }.AsQueryable());
    
                //this.ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
    
    
                //采用数据库中的数据来显示,所以要把上面的注释掉,这里就写自己的要实现注入的方法和接口
                this.ninjectKernel.Bind<IAccountBLL>().To<AccountBLL>();
            }
        }
    }
    

      然后要Gobal.asp.cs下面加载这个方法使得程序运行开始就知道控制器被扩展。

        不然重写控制器时就出出错。

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    using System.Web.Mvc;
    using System.Web.Optimization;
    using System.Web.Routing;
    using BookStoreUI.Infrastructure;
    using System.Data.Entity;
    using DAL.Entities;
    
    namespace BookStoreUI
    {
        // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
        // visit http://go.microsoft.com/?LinkId=9394801
    
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
    
                //Database.SetInitializer<EFDbContext>(null);
                //我们需要注册NinjectControllerFactory到MVC框架,所以我们也需要在Global.asax.cs里给它注册进去
                ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
            }
        }
    }
    

      

    最后在控制器里就可以实现你所用的注入方法。

    直接上代码:

    View Code
     1 using IBLL.Framework;
     2 using DAL.Entities;
     3 
     4 namespace BookStoreUI.Controllers
     5 {
     6     public class AccountController : Controller
     7     {
     8         private IAccountBLL iAccountBLL;
     9 
    10         public AccountController(IAccountBLL accountBLL)
    11         {
    12             iAccountBLL = accountBLL;
    13         }
    14 
    15         public ActionResult Index()
    16         {
    17             return View();
    18         }
    19 
    20         [HttpPost]
    21         public ActionResult Index(LoginViewModel model)
    22         {
    23             //验证码验证
    24             if (Session["__VCode"] == null || (Session["__VCode"] != null
    25                 && model.ValidateCode != Session["__VCode"].ToString()))
    26             {
    27                 ModelState.AddModelError("ValidateCode", "验证码出错");
    28                 return View();
    29             }
    30 
    31             if (ModelState.IsValid)
    32             {
    33                 Account account = iAccountBLL.ValidateAccount(model.Account.UserName, model.Account.PassWord);
    34 
    35                 //登录是否成功
    36                 if (account != null)
    37                 {
    38                     return RedirectToAction("BackIndex", "BackHome");
    39                 }
    40             }
    41 }
    42 }
  • 相关阅读:
    Javascript Read Excel
    Rest API 操作List Items
    web安全入门课程笔记——SQL漏洞分析与利用
    web安全入门课程笔记——网站基础与信息搜集
    博客迁移通知
    Python查找指定文件
    博客园写作避坑指南【持续更新】
    Changes of user relationship in AD can't be correctly synchronized to SCSM
    博客地址改为 https://0xcreed.jxustctf.top
    AI:WEB:1 Walkthrough
  • 原文地址:https://www.cnblogs.com/BuBu/p/2686559.html
Copyright © 2020-2023  润新知