马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
老周叕返来了,很久没写点什么了。声明一下,老周并不是没啥可写,真要写的,老周能写的东西可多了。毕竟老周聊发少年狂,左玩C,右++。表里兼修,戎码一生,天上地下海里都干过。潜水许久,先容老周表明一下。春节期间根本只做两件大事:远的不想去,近的玩腻了,正巧地铁修抵家门口。以是白天带着父母坐地铁到处溜;晚上吃完饭就给家里的灯啊、风扇等低功耗电路做大面积改造。率先实现家居环境工控化。以下是灌水时间,不看可以跳过哟。
过年前买好了配电箱、直流电源、分线器、继电器、MOS 管、工控板、三块 esp32 小板;红外传感器,告急是改楼梯口的灯,拆了开关,换成红外人体感应。
至于风扇,有两台改换成 12 V 的电机,结果不太好,以是其他的保持不改,互换 220V 买的是固态继电器,3V就能驱动,以是直接连单片机 IO 口没标题。贫苦的是要用 5V 的电源单独供电。
空调没有改,它们自己就自带 Wifi 控制。
----------------------------------------------------------------------------------------------------------------------------------------------
过完年了,又是客岁谁人某团体。客岁没调试出个结果,开年他们把呆板修睦了,然后又要已往继承调试。但这次破案了——当初老周猜疑是有人故意拔网线,末了发现不是人为捣乱,是互换机搞鬼,换了一台就齐备顺遂,迎来开年红了。
然后这个项目就要交接了,就是说,以后老周不给他们维护了,让他们自己的开发职员继承搞(他们自己养了 70 多人的开发团队,不消浪费)。于是,车间的事变告终后,要到他们团体工业区那边开了几个会,告急是给接办的人讲一下源代码,以及一些 Modbus 控制装备的原理。
----------------------------------------------------------------------------------------------------------------------------------------------
接着,经中学同砚先容,接了一个蓝牙 BLE 的项目,收罗木料数据的。花了 2.5 个星期弄好,现在已正式利用,现在他们厂那边没有反馈标题,应该是可以了案了。
迩来,又接了一个 ASP.NET Core 的,项目还没开始(也有大概会黄了),不知道干吗的。好像说是生产袜子的。另有一个是做游戏的,老周不会做,就推掉了。
-----------------------------------------------------------------------------------------------------------------------------------------------
好了,F 话讲完。下面是主题。分析一下,老周写的这系列 EF Core 可不算是 0 底子入门的,告急是分享现实利用本领,不能涉及每个知识点的。
地球人都知道,EF Core 的实体追踪是通过与从数据库查询出来的值举行比力来天生更新数据库的 SQL 的,但是,在现实利用时,咱们经常不必要先查询再更新的。比如,删除一条记录;登录时写入用户登录时间等。这些操纵没有须要把数据都查出来再去比力变动,再去更新。
固然说 EF Core 在 DbContext 类的 Database 属性所引用的 DatabaseFacade 对象上提供了如 ExecuteSqlRaw 如许的方法,答应直接发 SQL 语句,不外呢,如许玩的风格照旧太不像 EF 了。
于是,EF Core 又提供了另一套 API。可以绕过 ChangeTracker 来天生更新的 SQL 语句。用起来非常简单,咱们直接用实例解说。
1、打开 VS(大概长得像 VS 的 IDE),新建一个控制台应用项目。
2、实行菜单【工具】-【Nuget 包管理器】-【步伐包管理器控制台】,打开 Nuget 包控制台窗口。
3、在控制台中输入以下下令,活加 SQLite 的 EF Core 库。- install-package microsoft.entityframeworkcore.sqlite
复制代码 4、打开或新建代码文件。先界说实体类。- public class Photo
- {
- public int Pid { get; set; }
- public required string Title { get; set; }
- public int DPI { get; set; }
- public int Width { get; set; }
- public int Height { get; set; }
- public string? Tag { get; set; }
- }
复制代码 5、实现数据库上下文。- public class MyContext : DbContext
- {
- public MyContext(DbContextOptions<MyContext> ops)
- : base(ops)
- { }
- /// <summary>
- /// 数据集合
- /// </summary>
- public DbSet<Photo> Photos { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<Photo>(et =>
- {
- // 主键要配置,它不符合公共约定的格式
- <strong>et.HasKey(k => k.Pid).HasName("PK_Pid"</strong><strong>)</strong>;
- // 其他属性可以自动配置,没特别要求可以跳过
- });
- }
- }
复制代码 作为主键的属性叫 Pid,没法通过公共约定类主动设置为主键,以是要手动写一下。
6、可以为数据库上下文设置日志 来记录SQL语句(记得老周前面写过)。- // 先生成数据库上下文选项
- DbContextOptionsBuilder<MyContext> optBuilder = new();
- // 连接字符串
- optBuilder.UseSqlite("data source=hehe.db");
- // 过滤日志
,只记录生成的SQL - optBuilder.LogTo((eventId, logLevel) =>
- {
- // CommandExecuting 表示SQL执行前
- // CommandExecuted 表示SQL执行后
- // 两个事件任选其一都可以拿到SQL语句
- if (eventId.Id == RelationalEventId.CommandExecuted)
- {
- return true; // true 表示记录该日志
 - }
- return false; // false 表示不记录
- },
- eventData =>
- {
- if(eventData is CommandEventData cmdEvtData)
- {
- // 获取控制台当前的文本颜色
- ConsoleColor backup = Console.ForegroundColor;
- // 把文本改成地球颜色
- Console.ForegroundColor = ConsoleColor.Yellow;
- // 打印SQL
- Console.WriteLine($"已执行:{cmdEvtData.LogCommandText}");
- // 恢复文本颜色
- Console.ForegroundColor = backup;
- }
- });
复制代码 7、实例化数据库上下文,创建数据库,并放一点初始数据进去。- // 实例化数据库上下文
- using(var c = new MyContext(optBuilder.Options))
- {
- // 如果存在,删库跑路
- // 如果不存在,建库留守
- c.Database.EnsureDeleted();
- if(c.Database.EnsureCreated())
- {
- // 新库无数据,加点料
- c.Photos.Add(new Photo
- {
- Title = "山的对面有恐龙",
- Width = 50,
- Height = 35,
- DPI = 300,
- Tag = "休闲"
- });
- c.Photos.Add(new()
- {
- DPI = 300,
- Title = "清明上坟图",
- Tag = "祭祖,观光",
- Width = 1700,
- Height = 650
- });
- // 保存数据
- c.SaveChanges();
- }
- }
复制代码 着实,为新数据库备点新数据,可以在数据库模子设置阶段完成。- public class MyContext : DbContext
- {
- ……
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<Photo>(et =>
- {
- // 主键要配置,它不符合公共约定的格式
- et.HasKey(k => k.Pid).HasName("PK_Pid");
- // 初始数据
- <strong>et.HasData</strong>(new Photo
- {
- Pid = 1,
- Title = "山的对面有恐龙",
- Width = 50,
- Height = 35,
- DPI = 300,
- Tag = "休闲"
- },
- new()
- {
- Pid = 2,
- DPI = 300,
- Title = "清明上坟图",
- Tag = "祭祖,观光",
- Width = 1700,
- Height = 650
- });
- });
- }
- }
复制代码 注意假如用这种方法设置种子数据,Pid 要明白赋值,否则会报错。
不外,老周更保举以下方法:- // 先生成数据库上下文选项
- DbContextOptionsBuilder<MyContext> optBuilder = new();
- // 连接字符串
- optBuilder.UseSqlite("data source=hehe.db");
- ……
- // 初始化数据
- <strong>optBuilder.UseSeeding</strong>((context, _) =>
- {
- context.Photos.Add(
- new Photo
- {
- Title = "山的对面有恐龙",
- Width = 50,
- Height = 35,
- DPI = 300,
- Tag = "休闲"
- });
- context.Photos.Add(new()
- {
- DPI = 300,
- Title = "清明上坟图",
- Tag = "祭祖,观光",
- Width = 1700,
- Height = 650
- });
- context.Photos.Add(new Photo
- {
- Title = "燕子",
- Width = 500,
- Height = 400,
- DPI = 300,
- Tag = "动物"
- });
- // 保存到数据库
- context.SaveChanges();
- });
复制代码 UseSeeding 方法在 EnsureCreated 方法创建数据库后调用,它的用法和通例 DbContext 用法一样,因此 Pid 属性不必要显式赋值。
8、重点来了。下面咱们直接更新数据,不必要先实行查询。- using (MyContext context = new(optBuilder.Options))
- {
- int n = context.Photos
- .<strong>Where(x</strong><strong>=> x.Pid == 3</strong><strong>)</strong>
- .<strong>ExecuteUpdate</strong>(updsetBuilder =>
- {
- updsetBuilder.SetProperty(a => a.Tag, "下次拍更好的");
- });
- Console.WriteLine("更新了{0}条记录", n);
- }
复制代码 记得要先 Where 然后再调用 ExecuteUpdate 方法。调用 Where 方法是为了天生 WHERE 子句,不调用的话,那么 UPDATE 语句会更新全部数据记录。天生的 SQL 如下:- UPDATE "Photos" AS "p"
- SET "Tag" = @p
- <strong>WHERE </strong><strong>"p"."Pid" = 3</strong>
复制代码 ExecuteUpdate 方法必要用到名为 UpdateSettersBuilder 的类,它的作用就是你可以通过它来设置实体属性(通过表达式对象传入),EF Core 再通过传入的表达式来天生 SET 子句。该类的焦点就是 SetProperty 方法。- // 重载1
- SetProperty<TProperty>(Expression<Func<TSource,TProperty>> propertyExpression, TProperty valueExpression);
- // 重载2
- SetProperty<TProperty>(Expression<Func<TSource,TProperty>> propertyExpression, Expression<Func<TSource,TProperty>> valueExpression);
复制代码 咱们的示例用的是重载1,这两个重载的区别在第二个参数。第一个参数就是告 EF 你要设置实体的哪个属性,如 p => p.Tag,就是说我要设置 Tag 属性。
第二个参数咱们分开讲:
1、在重载1中,你直接提供要设置的值,示例中咱们用的就是如许;
2、在重载2中,第二个参数是 Expression,隐式转换后就是 Func 委托范例。它带有输入输出,为什么呢?这个告急是用于你修改时必要旧值的加入的环境。
比方,我要改DPI属性的值,这个值是在旧值底子上减掉 100。- int n = context.Photos
- .Where(x=> x.Pid == 3)
- .ExecuteUpdate(updsetBuilder =>
- {
- updsetBuilder.SetProperty(a => a.Tag, "下次拍更好的");
- updsetBuilder.SetProperty(a => a.DPI, <strong>a => (a.DPI - 100</strong><strong>)</strong>);
- });
复制代码 产生的 SQL 语句如下:- UPDATE "Photos" AS "p"
- SET "Tag" = @p,
- <strong>"DPI" </strong><strong>= "p"."DPI" - 100</strong>
- WHERE "p"."Pid" = 3
复制代码
另一种直接更新的操纵就是【删除】,对应的是 ExecuteDelete 方法。该方法用起来更简单。- int n = context.Photos
- .<strong>Where</strong>(p => p.Pid == 2)
- .<strong>ExecuteDelete</strong>();
- Console.WriteLine($"已删除{n}条记录");
复制代码 多数环境下,你都不能忘了调用 Where 方法,没有 WHERE 语句会删除全部数据记录!!!这一点肯定要注意。
上述代码删除 Pid 为 2 的数据记录,产生的 SQL 语句如下:- DELETE FROM "Photos" AS "p"
- WHERE "p"."Pid" = 2
复制代码
好了,本日的内容就到此了。老周都是一文聊一主题,内容简单的就多扯些别的,内容复杂的就多说些“端庄”话。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |