设为首页 收藏本站
查看: 1084|回复: 0

[经验分享] EntityFramework监控sql和EntityFramework中的事务

[复制链接]

尚未签到

发表于 2017-7-14 14:01:20 | 显示全部楼层 |阅读模式
  继续上篇:EntityFramework和EntityFramework.Extended使用说明——性能,语法和产生的sql

1.监控sql
  上篇中的sql监控采用的是 Microsoft SQL Server Management Studio中工具->profiler去监控的.
当然,Express版本是没有此功能的.
如果您使用不了profiler或者觉得不方便,那么,给出监控sql的第二方案.
  找到的资料是英文的,还好,容易理解.
原文链接:https://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/

a.控制台打印



var db = new PhoneBookEntities();//以后的db都是指它
db.Database.Log = Console.Write;//打印sql语句
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");//此语句不用db.SaveChanges();一样生效
  监控结果:



已于 2016/6/21 星期二 10:30:23 +08:00
打开了连接已于 2016/6/21 星期二 10:30:23 +08:00
启动了事务update GroupInfo set GroupName='hi' where GroupId=220
-- 正在 2016/6/21 星期二 10:30:23 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 10:30:23 +08:00
提交了事务已于 2016/6/21 星期二 10:30:23 +08:00
关闭了连接
b.记录sql到文件
  如果控制台打印不能满足您的需求,也可以记录到文件里.
方法:



var db = new PhoneBookEntities();
db.Database.Log = s => LogHelper.Write(s);//调用LogHelper类的方法
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");//此语句不用db.SaveChanges();一样生效
  LogHelper.cs



    public class LogHelper
{
public static void Write(string str)
{
var path = Path.Combine(new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).Parent.Parent.FullName, "logs.txt");
string errmsg = string.Format("{0}", str);
System.IO.File.AppendAllText(path, errmsg);
}
}
  就是这么简单!

2.EF中的事务
  上面例子看到产生的sql监控记录,
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");
此语句执行启动了事务.
  测试研究一下怎么回事.
以下两句:
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hi' where GroupId=209");
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=220");
经监控,分别启动并提交了两次事务.(如果sql命令为insert,delete也是同样道理)
  怎么把这两个sql语句放到一个事务里呢?别急,最后再说明.
  先看看最熟悉的db.SaveChanges()语句:以下语句本身没有实际意义,为了测试而写.



var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
ci.ContactName += "!";
gi.GroupName += "!";
db.SaveChanges();
ci.ContactName += "!";
gi.GroupName += "!";
db.SaveChanges();
  监控产生的sql:


DSC0000.gif DSC0001.gif


已于 2016/6/21 星期二 11:06:52 +08:00
打开了连接SELECT TOP (1)
[Extent1].[GroupId] AS [GroupId],
[Extent1].[GroupName] AS [GroupName]
FROM [dbo].[GroupInfo] AS [Extent1]
WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 1 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:06:52 +08:00
关闭了连接已于 2016/6/21 星期二 11:06:52 +08:00
打开了连接SELECT TOP (1)
[Extent1].[ID] AS [ID],
[Extent1].[ContactId] AS [ContactId],
[Extent1].[IsDelete] AS [IsDelete],
[Extent1].[Account] AS [Account],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[CommonMobile] AS [CommonMobile],
[Extent1].[HeadPortrait] AS [HeadPortrait],
[Extent1].[AttFile] AS [AttFile],
[Extent1].[GroupId] AS [GroupId]
FROM [dbo].[ContactInfo] AS [Extent1]
WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 1 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:06:52 +08:00
关闭了连接已于 2016/6/21 星期二 11:06:52 +08:00
打开了连接已于 2016/6/21 星期二 11:06:52 +08:00
启动了事务UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' (Type = String, Size = 300)
-- @1: '216' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 11:06:52 +08:00
提交了事务已于 2016/6/21 星期二 11:06:52 +08:00
关闭了连接已于 2016/6/21 星期二 11:06:52 +08:00
打开了连接已于 2016/6/21 星期二 11:06:52 +08:00
启动了事务UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' (Type = String, Size = 300)
-- @1: '216' (Type = Int32)
-- 正在 2016/6/21 星期二 11:06:52 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 11:06:52 +08:00
提交了事务已于 2016/6/21 星期二 11:06:52 +08:00
关闭了连接
监控记录  每次db.SaveChanges()会默认开启事务,执行sql语句,提交事务.多看看,好好理解一下.
  如何把两个db.SaveChanges()放到一个事务里呢?
  写法:



    var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
using (var tx = db.Database.BeginTransaction())
{
try
{
ci.ContactName += "!";
gi.GroupName += "!";
//db.SaveChanges();//这个语句影响到事务中sql的数量,有此语句事务里4条sql,没有就是2条.对于此案例,不影响结果.
ci.ContactName += "!";
gi.GroupName += "!";
db.SaveChanges();//必须要有
tx.Commit();//此语句不要漏了,否则监控结果会是释放了事务,而不是提交了事务!
    }
catch (Exception)
{
tx.Rollback();
}
}
  监控产生的sql:
  [没有第一个db.SaveChanges()]





已于 2016/6/21 星期二 11:20:49 +08:00
打开了连接SELECT TOP (1)
[Extent1].[GroupId] AS [GroupId],
[Extent1].[GroupName] AS [GroupName]
FROM [dbo].[GroupInfo] AS [Extent1]
WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:20:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:20:49 +08:00
关闭了连接已于 2016/6/21 星期二 11:20:49 +08:00
打开了连接SELECT TOP (1)
[Extent1].[ID] AS [ID],
[Extent1].[ContactId] AS [ContactId],
[Extent1].[IsDelete] AS [IsDelete],
[Extent1].[Account] AS [Account],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[CommonMobile] AS [CommonMobile],
[Extent1].[HeadPortrait] AS [HeadPortrait],
[Extent1].[AttFile] AS [AttFile],
[Extent1].[GroupId] AS [GroupId]
FROM [dbo].[ContactInfo] AS [Extent1]
WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:20:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:20:49 +08:00
关闭了连接已于 2016/6/21 星期二 11:20:49 +08:00
打开了连接已于 2016/6/21 星期二 11:20:49 +08:00
启动了事务UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:20:49 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:20:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 11:20:49 +08:00
提交了事务已于 2016/6/21 星期二 11:20:49 +08:00
关闭了连接
监控记录  [有第一个db.SaveChanges()]





已于 2016/6/21 星期二 11:21:49 +08:00
打开了连接SELECT TOP (1)
[Extent1].[GroupId] AS [GroupId],
[Extent1].[GroupName] AS [GroupName]
FROM [dbo].[GroupInfo] AS [Extent1]
WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 1 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:21:49 +08:00
关闭了连接已于 2016/6/21 星期二 11:21:49 +08:00
打开了连接SELECT TOP (1)
[Extent1].[ID] AS [ID],
[Extent1].[ContactId] AS [ContactId],
[Extent1].[IsDelete] AS [IsDelete],
[Extent1].[Account] AS [Account],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[CommonMobile] AS [CommonMobile],
[Extent1].[HeadPortrait] AS [HeadPortrait],
[Extent1].[AttFile] AS [AttFile],
[Extent1].[GroupId] AS [GroupId]
FROM [dbo].[ContactInfo] AS [Extent1]
WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:21:49 +08:00
关闭了连接已于 2016/6/21 星期二 11:21:49 +08:00
打开了连接已于 2016/6/21 星期二 11:21:49 +08:00
启动了事务UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:21:49 +08:00
执行-- 已在 0 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 11:21:49 +08:00
提交了事务已于 2016/6/21 星期二 11:21:49 +08:00
关闭了连接
监控记录  解决最初的问题:



    var gi = db.GroupInfo.FirstOrDefault(c => c.GroupName.Contains("g1!"));
var ci = db.ContactInfo.FirstOrDefault(c => c.ID == 12);
ci.ContactName += "!";//
    gi.GroupName += "!";  //这两句放到了using外面,也是可以的
using (var tx = db.Database.BeginTransaction())
{
try
{
db.Database.ExecuteSqlCommand("update GroupInfo set GroupName='hello' where GroupId=209");
db.SaveChanges();//这个语句
tx.Commit();//此语句不要漏了,否则监控结果会是释放了事务,而不是提交了事务!
        }
catch (Exception)
{
tx.Rollback();
}
}
  监控记录:





已于 2016/6/21 星期二 11:28:28 +08:00
打开了连接SELECT TOP (1)
[Extent1].[GroupId] AS [GroupId],
[Extent1].[GroupName] AS [GroupName]
FROM [dbo].[GroupInfo] AS [Extent1]
WHERE [Extent1].[GroupName] LIKE N'%g1!%'
-- 正在 2016/6/21 星期二 11:28:28 +08:00
执行-- 已在 1 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:28:28 +08:00
关闭了连接已于 2016/6/21 星期二 11:28:28 +08:00
打开了连接SELECT TOP (1)
[Extent1].[ID] AS [ID],
[Extent1].[ContactId] AS [ContactId],
[Extent1].[IsDelete] AS [IsDelete],
[Extent1].[Account] AS [Account],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[CommonMobile] AS [CommonMobile],
[Extent1].[HeadPortrait] AS [HeadPortrait],
[Extent1].[AttFile] AS [AttFile],
[Extent1].[GroupId] AS [GroupId]
FROM [dbo].[ContactInfo] AS [Extent1]
WHERE 12 = [Extent1].[ID]
-- 正在 2016/6/21 星期二 11:28:28 +08:00
执行-- 已在 1 毫秒内完成,结果为: SqlDataReader

已于 2016/6/21 星期二 11:28:28 +08:00
关闭了连接已于 2016/6/21 星期二 11:28:28 +08:00
打开了连接已于 2016/6/21 星期二 11:28:28 +08:00
启动了事务
update GroupInfo set GroupName='hello' where GroupId=209
-- 正在 2016/6/21 星期二 11:28:28 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[ContactInfo]
SET [ContactName] = @0
WHERE ([ID] = @1)
-- @0: '李四1!!!!!' (Type = String, Size = 50)
-- @1: '12' (Type = Int32)
-- 正在 2016/6/21 星期二 11:28:28 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1
UPDATE [dbo].[GroupInfo]
SET [GroupName] = @0
WHERE ([GroupId] = @1)
-- @0: 'g1!!!!!!' (Type = String, Size = 300)
-- @1: '222' (Type = Int32)
-- 正在 2016/6/21 星期二 11:28:28 +08:00
执行-- 已在 1 毫秒内完成,结果为: 1

已于 2016/6/21 星期二 11:28:28 +08:00
提交了事务已于 2016/6/21 星期二 11:28:28 +08:00
关闭了连接
监控记录  事务部分,我参考的网址:https://msdn.microsoft.com/zh-cn/magazine/dn532202.aspx
   https://msdn.microsoft.com/en-us/data/dn456843#retry
  解释: Name += "!";这么写而不是 Name="李四"; 是为了防止EF的自动优化sql.
  over...

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-393770-1-1.html 上篇帖子: 记一次SQL注入实战 下篇帖子: EntityFramework Core Raw SQL
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表