【EF】知识笔记

EF添加数据、查询数据

使用EF添加数据、查询数据

EF大数据批量处理----BulkInsert

EF更新数据库字段的三种方法

实体类

   public class TestDbContext : DbContext
    {
        public DbSet<Test> Tests { get; set; }
        public TestDbContext() : base() { }
    }
    public class Test
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Remarks { get; set; }
    }

创建数据

            TestDbContext db = new TestDbContext();
            db.Tests.Add(new Test() { Name = "测试1", Email= @"123@abc.com", Remarks = "测试1备注"});
            db.Tests.Add(new Test() { Name = "测试2", Email = @"456@abc.com", Remarks = "测试2备注"});
            db.SaveChanges();

第一种方法:

  先查询记录,然后修改相应的属性。此方法虽然多了一个查询步骤,但是也由此利用了EF的自动跟踪功能,后续操作比较方便。

比如,生成的SQL语句只会去修改相应的修改过的字段。

而且经测试发现,如果实体属性值没有改变,不会生成SQL语句,比如将下面的代码执行两次,第二次 SaveChanges() 方法不会执行SQL更新语句(注:由于还是会执行一次查询,所以运行效率并没有显著提升)

TestDbContext db = new TestDbContext();
var test = db.Tests.Find(1);
test.Remarks = "更新字段方法1";
db.SaveChanges();

第二种方法:

  直接创建一个新的实体类,然后修改实体对象的状态。此方法虽然少了一个查询步骤,但生成的SQL语句将会修改全部字段,而且还要确保 ID 值存在。(注意:由于会修改全部字段,没有设置的字段会被设置为null

TestDbContext db = new TestDbContext();
Test test = new Test() { ID = 1, Remarks = "更新字段方法2" };
db.Entry(test).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();   

第三种方法:

  创建一个实体类,将实体附加到数据库上下文,然后修改相应属性值的修改标识为 true ,此方法生成的SQL语句与第一种方法一样,比较简洁,而且还少了查询步骤,只是后续的操作比较麻烦,因为要手动设置各个属性的修改标识,还要确保 ID 值存在。

 TestDbContext db = new TestDbContext();
            Test test = new Test() { ID = 1, Remarks = "更新字段方法3" };
            db.Tests.Attach(test);
            db.Entry(test).Property("Remarks").IsModified = true;
            db.SaveChanges();

生成的SQL语句(使用 SQL Server Profiler 跟踪数据库所得):
第一种方法:(注:第一种方法的代码执行一次后再次执行没有跟踪到更新数据库的SQL语句)

exec sp_executesql N‘UPDATE [dbo].[Tests]
SET [Remarks] = @0
WHERE ([ID] = @1)
‘,N‘@0 nvarchar(max) ,@1 bigint‘,@0=N‘更新字段方法1‘,@1=1

第二种方法:(注:查看SQL语句可知,使用此方法如果不注意可能会导致数据被错误修改

exec sp_executesql N‘UPDATE [dbo].[Tests]
SET [Name] = NULL, [Email] = NULL, [Remarks] = @0
WHERE ([ID] = @1)
‘,N‘@0 nvarchar(max) ,@1 bigint‘,@0=N‘更新字段方法2‘,@1=1

第三种方法

exec sp_executesql N‘UPDATE [dbo].[Tests]
SET [Remarks] = @0
WHERE ([ID] = @1)
‘,N‘@0 nvarchar(max) ,@1 bigint‘,@0=N‘更新字段方法3‘,@1=1

EF添加记录时获取自增ID值

Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增值返回给实体对象对应的属性。

比如下面添加博客随笔至数据库的示例代码:

var blogPost = new BlogPost()
{
    Author = "博客园",
    Title = "程序员的网上家园"
};
using (BlogDbContext context = new BlogDbContext())
{
    context.BlogPosts.Add(blogPost);                
    context.SaveChanges();
    return blogPost.ID;
}
View Code

SaveChanges()之后,blogPost.ID的值就是数据库中对应自增标识列的值

看一下Entity Framework生成的SQL语句:

exec sp_executesql N'insert [dbo].[blog_Content]([Title],[Author])

values (@0, @1)

select [ID]

from [dbo].[blog_Content]

where @@ROWCOUNT > 0 and [ID] = scope_identity()',

N'@0 nvarchar(128),@1 nvarchar(128),',@0=N'程序员的网上家园',@1=N'博客园'

  EF通过scope_identity()获取自增列的值,而且我们没有对BlogPost的ID属性进行任何设置,是EF智能地判断出ID就是自增标识列

在以前没有使用Entity Framework的时代,用的是存储过程,存储过程有一堆参数,实体对象的属性值要一一对应地赋值给这些参数,执行存储过程之后,还要通过ParameterDirection.Output的参数获取自增ID的值。

EF中 一例对一个或多个实体的验证失败。有关详细信息,请参阅“EntityValidationErrors”属性的解决

注:add数据时 最好加异常捕获(以防一些必填字段没有赋值)

这个问题相信只要是做MVC的,都碰到过,也都知道错误的原因,就是触发了定义的实例字段校验规则。比如定义的不为空,但是为空了,或者定义的字段长度为50,但是超过50了。

可是有时虽然知道是这样,但是具体问题解决的时候还是无从下手。我最近就碰到一个,知道是在更新某个表的时候出现的这个问题。可是在本地无法具现此错误,这个错误是在特定条件发生的,我并不知道此特定发生条件是什么,很郁闷。

在网上找了下,知道发生这个错误会触发DbEntityValidationException异常,这个异常会有详细的异常信息说明是哪个字段,出现了什么错误,只不过需要循环输出。打算输出到日志文件中看是什么错误。代码如下:

try
            {
                es2.Update(examList);
            }
            catch (DbEntityValidationException dbEx)
            {
                foreach (var validationErrors in dbEx.EntityValidationErrors)
                {
                    foreach (var validationError in validationErrors.ValidationErrors)
                    {

                        EventLog.Log(string.Format("Class: {0}, Property: {1}, Error: {2}", validationErrors.Entry.Entity.GetType().FullName,
                        validationError.PropertyName,
                        validationError.ErrorMessage), "error");
                    }
                }

            }
            catch (Exception ex)
           {
                throw;
            }
finally
            {
            }
View Code

之所以用2个catch,是为了防止有其他非DbEntityValidationException 错误时,没有错误日志。

DbEntityValidationException所在命名空间:System.Data.Entity.Validation

编译,上传到服务器,过了一会,查看日志文件,找到错误原因了。

 Class: System.Data.Entity.DynamicProxies.ExamList_839A196D8FC4CF7E8A791B7F29782BA535E73532A1C3C2C00FD6EF30B6C4A660, Property: StudentAnswer, Error: 字段 StudentAnswer 必须是最大长度为 50 的字符串。
是StudentAnswer 字段长度不够了。

vs2017中没有EF模型的问题

在添加->新建项目 中找不到实体模型?

或者 在vs中打开edmx文件时,显示的只有文本,没有图形模式

原因:是因为没有安装实体模型插件

解决方法:

1、打开网址

https://marketplace.visualstudio.com/items?itemName=ErikEJ.EntityFramework6PowerToolsCommunityEdition

2、下载程序,关闭vs2017,点击下载的文件安装。

3、重新打开vs2017就可以了。

 

posted @ 2018-10-08 20:10  peterYong  阅读(1993)  评论(0编辑  收藏  举报