Code First操作Mysql数据库

时间:2023-03-08 16:54:08

前面博客也讲了,自己做一个网站,选用的是MVC+EF Code First+MySql+EasyUI,先说下技术选型。
一、为什么选择MVC?

因为之前自己做的系统大部分是webForm,MVC的之前也做过但是也都是框架已经搭好的,所以选择使用MVC框架,自己也搭建下MVC类型的框架。MVC也比webForm也更加方便容易开发。

二、为什么选择EF Code First呢?

这个说起来惭愧,C#不用Code First也是可以访问Mysql数据库的,只要下载C#访问MySQL数据库的ADO.NET驱动程序 mysql-connector-net(http://www.mysql.com)、引入Mysql.Data.dll类库,然后使用Mysqlhelper来访问数据库,这样的也是要先设计数据库,然后访问数据库,从数据库查询数据,但是这种也是有弊端,我刚开始的时候就是想用这种方式,当我遇到要分页的时候我就傻眼了,使用sql分页也是特别麻烦。所以就选择了CodeFirst,这样更加方便。

三、为什么使用Mysql呢?

这个不是我能做主的,华为那边的客户给的就是一个mysql的数据库,哎,不过想想自己在使用mysql的过程中也学到好多东西。

四、为什么选择EasyUI?

之前也用过类似的前端框架,像ligerui,但easyui之前没用过,所以想着自己用着试试,所以就选择了EasyUI。

五、在搭建框架中遇到的问题?

1.Code First操作MySQL数据库

今天就是主要解决了这个问题,公司不能访问外网,不能使用Negut来管理dll。所以还是我自己在家里把EntityFramework.6.1.3、MySql.Data.6.9.9、MySql.Data.Entity.6.9.9下载发到公司邮箱中。如果没安装就会出现下面的错误.

Code First操作Mysql数据库

安装之后可不是万事大吉了,坑是一个接着一个,连接数据库的时候又会出现下面的错误。

Code First操作Mysql数据库

这个错误需要在数据库中执行下面的一句sql

set global optimizer_switch='derived_merge=OFF';

还需要修改配置文件数据库上下文放在了Model层,数据库上下文的ConnectionString虽然是在Model层,但还是应该将连接字符串放在Web层的webConfig中。然后要修改配置文件如下:注意版本号

<?xml version="1.0" encoding="utf-8"?>
<!--注意:此项目为动态库,所以此配置文件内容仅供作为范本使用,实际的WPF或ASP.NET项目可从此文件复制配置内容进行修改-->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <!--MySQL启用下面一行-->
  <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
  <!--SQL SERVER 启用下面一行-->
  <!--entityFramework-->
    <contexts>
      <!--通过设置disableDatabaseInitialization="true",可以禁止数据库初始化操作-->
      <context type="EF6CodeFirstMySQL.Model.DataModelContext,EF6CodeFirstMySQL.Model" disableDatabaseInitialization="false">
        <databaseInitializer type="EF6CodeFirstMySQL.Model.DataModelInitializer,EF6CodeFirstMySQL.Model"></databaseInitializer>
      </context>
    </contexts>
    <!--MySQL启用下面一段配置项-->
    <defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <!--SQL SERVER 启用下面一行-->
    <!--defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /-->
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
    </providers>
  </entityFramework>
  <connectionStrings>
    <!--MySQL启用下面一行-->
    <add name="DataModelContext" connectionString="Data Source=localhost;port=3306;Initial Catalog=EF6CodeFirstDemo;user id=root;password=123456;" providerName="MySql.Data.MySqlClient" />
    <!--SQL SERVER 启用下面一行,注意数据库文件路径中使用了|DataDirectory|宏变量,该变量只在ASP.NET项目中有效-->
    <!--add name="DataModelContext" connectionString="Data Source=.;database=EF6CodeFirstDemo;uid=sa;pwd=123456;AttachDBFilename=|DataDirectory|\XantFlowDB.mdf;" providerName="System.Data.SqlClient"/-->
  </connectionStrings>
 
  <system.data>
    <DbProviderFactories>
      <remove invariant="MySql.Data.MySqlClient" />
      <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
  </system.data>
</configuration>

2.EasyUI分页的问题?

前面也讲了为什么选择EF Code First来操作Mysql,分页就是其中的一个原因。因为如果使用之前通过sql访问那还有写通用分页sql,找到总行数和对应页的数据。但是有了code First后,就不用那么麻烦,直接使用Take()和Skip()来分页。这里主要说下分页的思路。在EasyUI中的DataGrid中可以设置分页属性来控制是否分页,如果分页,在easyui请求后天数据时会自动带上页码和每页的数量,这个要注意的是页码是从1开始的,而take()、skip()是从0开始的。然后返回count、row即可分页,所以选择了EF来操作mysql。

参考:http://www.cnblogs.com/joeymary/p/5634262.html

3.EF Code First多对多的查询问题,这个问题算是属于自己没把Linq知识学的透彻导致的。

项目中有实体关系是多对多的关系,由于采用code First,数据库会自动生成一个中间表来映射多对多的关系,但在实体类中这个关系并没体现,只是在每个类中添加了对方的List类型的属性。例如User、Role,一个User可以有多个Role,而一个Role又可以拥有多个User。

    class User
{
[Key]
public int Id { get; set; } public string UserName { get; set; } public List<Role> Roles { get; set; }
}
    class Role
{
[Key]
public int Id { get; set; } public string RoleName { get; set; } public List<User> Users { get; set; }
}

由于想着按照数据库的那套思想连接查询,但是连接查询的时候就出现问题了,两个表怎么连接呢?在linq join 后的on怎么写呢?所以就傻眼了,害我在项目中吭哧吭哧的还写了视图使用code first执行sql来执行视图来解决,这几天也一直在想这个问题,之前一直搜Code First多对多查询,都没我想要的结果,突然就要躺下的时候突然想到这不是Code First的问题,因为即使没有Code First也有多对多,Code First只是提供数据的一种方式,所以这他妈原来是Linq的问题,搜索Linq多对多查询,正好看到http://blog.sina.com.cn/s/blog_4a1489560100ctez.html这一贴子,看到之后才发现是自己傻逼了,这不是From子句吗,这主要还是自己玩Linq还玩的不好,看来有必要继续学习的Linq。

            User userA = new User() { UserName="UserA"};
User userB = new User() { UserName = "UserB" };
Role RoleA = new Role() { RoleName="RoleA"};
Role RoleB = new Role() { RoleName = "RoleB" }; using (var db = new MyContext())
{
userA.Roles = new List<Role>() { RoleA, RoleB };
userB.Roles = new List<Role>() { RoleB };
db.Users.AddRange(new List<User> { userA, userB });
db.SaveChanges();
var data = (from p in db.Users
from s in p.Roles
select new RoleUser { UserName= p.UserName, RoleName=s.RoleName }).ToList(); }

4.现在匿名对像View显示的问题

上面的代码可以看到通过from子句查询多对多的关系,select出RoleUser对象,这个对象是ViewModel,我之前想着用匿名对象返回给View,但是在View中foreach遍历时并不能取到对应的值,所以这边又声明了一个ViewModel。