最近做了个winform小项目,为方便快速开发,后台框架使用了ef6.0+sqlserver2008架构,遇到各种问题,真是伤脑筋。现将遇到问题和解决方案写下来,方便查阅
No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'. Make sure the provider is registered in the 'entityFramework' section of the application config file.
这个问题比较坑,我根据上面的提示,跑到配置文件去查看,看有没有entutyFramework节点,是否注册驱动。结果按照网上的解决方案把配置文件贴上去了还是报错,然后再查看EntityFramework.SqlServer.dll是否已经引用到数据访问层类库中,也在。这下就懵逼了,到底是什么情况,网上各种搜,比如把EntityFramework.SqlServer.dll的赋值到本地属性设为True后还是没有用,折腾了个把小时,最后突然看了一眼bin\Debug目录,发现只有一个EntityFramework.dll文件,没有EntityFramework.SqlServer.dll,我就瞬间释然了,原来是这样。。。
1.检查是否引入EntityFramework.dll 和EntityFramework.SqlServer.dll
2.检查是否设为复制到本地属性为True
3.检查配置文件是否注册驱动
如我的是sqlserver数据库:
<providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers>
如果是mysql
<providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider> </providers>
将上面这段代码放到<entityFramework>节点下面就可以了,并且要引入几个dll
4.查看编译后的目录中是否有这2个dll,如果没有,手动拷贝进去
有时候新加了一个实体类,数据库也相应加了一个表。然后理所当然的运行增加数据,结果就出现这提示
然后又是一阵排查,再次确认了数据库中确实存在表,还手动存进去了一条数据。再跑到BaseContext:DbContext这个类里面一阵翻,确定已经有 public DbSet<Employee>a_Emp { get; set; }这个属性了。又跑到实体类中确认字段是否吻合,主键[key]标记是否已经标了。最后又对比了之前的项目2个实体之间的差别。最后终于发现。。。实体类没有和数据库关联
1.确认数据库表是否存在
2.确认BaseContext:DbContext类中是否有属性
3.确认实体类中字段与主键
4.确认实体与数据库表是否关联
[Table("a_Emp")] public class Employee
另:实体类上面的[table]小括号里面的就是数据库的表名,并且该标记需要引用dll
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema;
这个问题是数据库字段为空导致的,ef 反射赋值时实体时发生的错误,如:ToList()、
_db.Set<TEntity>().AddRange(entry);
_db.SaveChanges();
2种任选一种
1.将数据库所有字段都赋值,不存在为空的情况 自然不会报错,但毕竟繁琐
2.将数据库中可空字段再实体中用可空类型表示
如:
public DataTime? CreateTime{get;set;} public int? Num{get;set;} public decimal? Pirce{get;set;}
目前我知道的就这2种,应该够用了
外键是常用的数据关联形式,在数据访问中占据重要位置,下面来看看使用外键的几个步骤
一、将2个实体类都准备好,一个主键表一个外键表,例如 员工表中需要部门编号 那么就需要准备员工类和部门类
二、在员工实体类Employee中加入一个对象实体,加一个部门Id,没错,不是一个单纯的部门ID 而是实体
[Key] public int EmpId { get; set; } /// <summary> /// 姓名 /// </summary> public string EmpName { get; set; } /// <summary> /// 性别 /// </summary> public string Sex { get; set; } /// <summary> /// 生日 /// </summary> public DateTime BirthDay { get; set; } /// <summary> /// 部门 /// </summary> public int DepId { get; set; } /// <summary> /// 关联主表 /// </summary> [ForeignKey("DepId")]
public Dept Dept { get; set; } //注意:ForeignKey("DepId")中的DepId 就是员工类的外键
四、Dept部门表中必须有主键
五、调用的时候
db.a_Emp.Include("Dept").Where(l => l.Dept.name.Contains(name)||string.IsNullOrEmpty(name)).ToList()
其中a_Emp是员工类的实体对象,在baseContext里面的 public DbSet<Employee>a_Emp { get; set; }
Dept.name是可以直接点出来的了
使用mvc时会用到权限控制,并且存cookie,然后一般会出现下面的一段代码
protected override void OnActionExecuting(ActionExecutingContext filterContext) { var request = filterContext.HttpContext.Request; var response = filterContext.HttpContext.Response; currentUser = new AdminUser(); if (filterContext.HttpContext.User.Identity.IsAuthenticated) { long.TryParse(System.Web.HttpContext.Current.User.Identity.Name, out userid); if (userid > 0) { currentUser = AdminUserDAL.getEntryById<AdminUser, long>(userid); currentUser.allprivileges = AdminUserDAL.getUserPrivilegeAll(-1, userid); myPermissionList = currentUser.allprivileges; } } else //返回登录页 { response.Redirect("/Acount/Login"); }
一直为false的时候就会出现始终跳到登录页,就算调试也找不到为什么会这样
在webconfig文件的system.web节点下面加入节点就行了
<authentication mode="Forms"> <forms loginUrl="~/Home/Login" name="paochi.com" timeout="300" protection="All" path="/" requireSSL="false" slidingExpiration="false" enableCrossAppRedirects="false" cookieless="UseCookies" /> </authentication>
里面的内容可以自己根据需要配置
以上是我遇到的众多问题之一,限于篇幅和时间,暂时就记录到这里吧。如果有什么理解错误的地方,还望指正!!!
请关注我的博客地址:http://www.cnblogs.com/jingch 给个赞吧!