标签:档案EFCore

链接到我最近的ddd+efcore内容

我所创建的各种文章和视频的聚合时间已经足够长了,其中包含了有关ef核心支持如何将域模型直接映射到关系数据库的课程,这些支持已经得到了改进:


宣布:深入研究英孚核心2天研讨会

6月17-18日在伦敦与我一起深入探讨实体框架核心,为期两天。yabo官网

这是一个新添加的技能物质课程目录。因为这是一门新课程,我们希望获得关于拟涵盖主题列表的反馈。如果你有兴趣参加,您的输入将有所帮助。

主题列表在2天内是否太长?它是否涉及到你想在高级课堂上学习的内容?您可以提供关于课程描述页

第1天:利用高级功能

  • EF核心与EF6差异的高水平回顾
  • 实现日志记录以捕获ef core的数据库和内存中的活动。了解要捕获的不同类型的日志记录数据
  • 学习各种播种方法,例如通过数据库脚本,代码或使用EF Core 2.1中引入的基于迁移的播种。您还将了解每种方法何时合适
  • 在开发、源代码管理和部署期间使用迁移
  • 集成测试您的EF核心代码

第2天:软件架构中的EF核心

  • 关于存储库的大辩论:用于公开EF核心的存储库模式/通用存储库的利弊
  • 设计数据层/ api
  • 了解复杂的映射约定,并使用Fluent API使用自定义映射对其进行补充。
  • 设计性能
  • *奖金主题*如果涵盖了所有模块,您还将在Azure函数中查看ef core,并在Azure Cosmos DB中查看ef core(给定足够的时间)

登录ef core 2.2有一个更简单的语法——更像是asp.net core

记录ef-core的内存操作和SQL操作自ef-core到来以来已经发展了几次。它利用了与ASP.NET核心使用的相同的底层功能。如果您使用的是ASP.NET核心,日志记录是经过烘焙的,对于ef核心打开它并添加过滤非常简单。参见Shawn Wildermuth的博客文章ASP.NET核心中的EF核心日志记录

但是如果您不使用ASP.NET核心,这有点复杂。不是很可怕,但仍然有一些额外的工作要做。它涉及在dbContext中设置iLoggerFactory并同时定义任何过滤器。

我在之前的msdn杂志上写了一篇关于这个的文章(重点是利用ef核心日志记录的各种可用过滤器),哦,等等,今天是1月1日,所以我可以说“最后一年”。数据点–在EF核心中记录SQL和更改跟踪事件。我也在我的EF核心2入门课程,EF核心2:映射EF核心2.1:新功能多元化课程。(请注意,我已经将入门课程的示例代码更新为ef core 2.2,并将其放到了github上github.com/julielerman/multiplesightefcore2getingstarted

我的文章和课程使用控制台应用程序来演示EF核心行为,因此控制台日志提供者将日志程序与控制台联系起来。请注意,数据点文章包含了许多关于各种过滤类型的详细信息。所以您可以使用下面的新语法来指定应该有一个过滤器,但是一定要阅读这篇文章来了解过滤的风格,以及根据您所做的选择,您能够看到哪些类型的细节。

但是日志API不断发展,并提供了一些与ASP.NET创建的相同的快捷方式。并且consoleloggerprovider已被弃用。API不是EF核心的一部分。它是。net Core的一部分。EF核心和ASP.NET核心都使用它。

如果您使用的是EF Core 2.2,语法已经改变了(简化了),在3.0中它将变得更加流线型。

事实上,如果将前面的语法与2.2一起使用,您将收到有关ConsoleLoggerProvider的警告:

obsolete(“此方法已过时,将在未来版本中删除。推荐的替代方法是使用LoggerFactory配置过滤,使用ConsoleLoggerOptions配置日志记录选项。

就比较而言,下面是一个使用旧语法打开日志记录的示例,只显示与数据库命令相关的日志,只显示标记为“信息”的消息。

EF Core 2.0和2.1逻辑

public static readonly loggerfactory myconsoleloggerfactory=new loggerfactory(new[]new consoleloggerprovider((category,level)=>category==dbloggercategory.database.command.name&&level==loglevel.information,真实)};

一旦在context类中定义了logger工厂字段,就告诉DbContext在配置时使用它。

protected override void onconfiguring(dbContextOptionsBuilder OptionsBuilder)var connectionString=configurationManager.connectionStrings[“wpfdatabase”].toString();选项builder.useloggerfactory(myconsoleloggerfactory)。启用敏感数据记录(true)。usesqlserver(connectionString);}

所以这是记录器工厂的创建,它的语法有点复杂。新的API遵循了ASP.NET核心如何让您使用以过滤器为参数的addfilter方法进行过滤。不需要羔羊。另外,配置过滤器是一个单独的逻辑位,用于通知日志记录器它应该绑定到控制台。

EF核心2.2逻辑

有了EF核心2.2,您可以在构造函数或其他方法中设置记录器工厂,只要在配置选项生成器时该工厂可用。我在一个方法中创建它,然后使用该方法作为useLoggerFactory的参数。我仍在筛选只显示标记为信息的数据库命令和日志详细信息。

{IServiceCollection serviceCollection = new serviceCollection ();servicecollection.addlogging(builder=>builder.addconsole().addfilter(dbloggercategory.database.command.name,loglevel.information));返回ServiceCollection.BuildServiceProvider().GetService
             
              ();}
             

然后在选项builder的useLogging方法中调用getLoggerFactory():

optionsBuilder.UseLoggerFactory (GetLoggerFactory ())

文件包和参考

为了使用addconsole()方法,你还得用Microsoft.Extensions.Logging.Console以前的consoleloggerprovider所在的包。然而,命名空间不需要using语句(就像对consoleloggerprovider所做的那样)。

EF核心配置和日志记录

我对今天的一些行为有点困惑,最后意识到我的错误,所以我想我会分享它。这主要发生在我正在构建的不使用ASP.NET核心的演示应用程序中。

在这些情况下,我通常将dbContext提供程序配置坚持在onModelConfiguring方法中。例如,如果我用的是sqlite,然后我将在方法中指定如下:

保护覆盖无效配置(dbContextOptionsBuilder选项Builder)选项builder.usesqlite(@“filename=data/pubstracker.db”);}

我也经常使用伐木厂。定义之后,我也配置它。我不太考虑我在哪里,所以把它随意地加了进去。

受保护的覆盖无效配置(dbContextOptionsBuilder OptionsBuilder)OptionsBuilder.useLoggerFactory(myConneleLoggerFactory);选项builder.usesqlite(@“filename=data/pubstracker.db”);}

然后我在一些测试中添加了不得不避免SQLite提供程序(如果InMemory提供程序已经配置好了),因此,我对usesqlite方法进行了包装,检查是否已经配置了选项生成器。

受保护的覆盖无效配置(dbContextOptionsBuilder OptionsBuilder)OptionsBuilder.useLoggerFactory(myConneleLoggerFactory);如果(!)optionsbuilder.isconfigured)optionsbuilder.usesqlite(@“filename=data/pubstracker.db”);}}

但我的逻辑行不通。我运行了一些迁移,但是他们突然不认识UseSqlite方法。这个句型我用过很多次了。我过了一会儿才意识到发生了什么事。使用记录器工厂是一个配置

我只需要在配置了检查之后移动useloggerfactory逻辑,一切都很好。

这是一件非常愚蠢的事情,你根本想不到别人会犯这样的错误。但因为它咬了我,我认为这是值得分享的,主要是为了下一个编码器谁是试图解决相同的问题。

新Pluralsight课程!EF核心2:入门

我最近在multuralsight.com上发表了我的第19门课程:实体框架核心2:开始yabo官网

它长2小时40分钟,专注于基础知识。

这是在Visual Studio 2017中使用的ef core 2.0.1。

未来计划:我已经开始了一个中级课程的后续工作,并有其他人参与其中……例如,当ef core 2.1发布(我将等到它有了rtmd以获得稳定性)和其他高级主题时,它将涵盖其功能。我还计划在MacOS上使用vs代码进行跨平台版本的开发,因为这是我最近的最爱。

如果你不是一个多元化的订户,给我寄张便条我可以给你30天的试用期,这样你就可以观看课程了。警告:该试验类似于成为订户的网关药物。

这是目录这门课

介绍一个新的,重量较轻版本的EF 32m 40s
简介和概述
什么是实体框架核心?yabo官网
您可以在其中构建和运行具有EF核心的应用程序
EF Core如何工作
从ef6到ef core到ef core的路径
EF核心2的新功能
展望EF Core 2.1及以后版本
审查和资源

使用EF Core 42m 36s创建数据模型和数据库
简介和概述
设置解决方案
使用nuget包管理器添加ef core
使用EF Core创建数据模型
指定数据提供程序和连接字符串
了解EF核心迁移
添加第一次迁移
检查您的第一次迁移
使用迁移编写脚本或直接创建数据库
在.NET核心中重新创建模型
添加多对多和一对一关系
对现有数据库进行反向工程
审查和资源

与您的EF核心数据模型34M 11S交互
简介和概述
让EF Core输出SQL日志
插入简单的对象
保存时批处理命令
查询简单对象
在查询中过滤数据
更新简单对象
断开连接的更新
删除带有EF内核的对象
审查和资源

查询保存相关数据20M 49S
简介和概述
插入相关数据
预加载相关数据
在查询中投影相关数据
使用相关数据筛选对象
修改相关数据
审查和资源

在应用程序中使用EF核心30M 52S
简介和概述
桌面或设备上的EF核心
桌面应用程序:Windows表示基础(WPF)
创建WPF应用程序
遍历WPF数据访问
ASP.NET核心MVC中的EF核心
将相关数据添加到MVC应用程序中
对MVC应用程序的关系进行编码
审查和资源

从net core或net标准类库运行ef core 2.0迁移的秘密

我有两个人看着我多元视野核心入门课程(即将加入英孚核心2:入门课程)问同样的问题,一开始让我迷惑。

正在运行导致项目编译的迁移命令,但是命令没有做任何事情。例如,add-migration没有添加迁移文件。get dbContext未返回任何信息。最奇怪的是没有错误信息!我能把这个问题复制出来。

有了EF6,就可以从类库中使用迁移,而不需要看到任何exe项目。EF核心迁移可以从.NET框架或.NET核心项目运行,但不能从.NET标准运行。它需要一个运行时。一个常见的解决方法是,即使你还没有进入应用程序的用户界面部分,要将.NET核心控制台应用程序项目添加到解决方案中,添加ef core design nuget包并将其设置为启动项目。但在不添加虚拟项目的情况下仍然可以这样做。

我们已经知道了多目标修复,它解决了当您尝试从.NET标准库运行迁移时的错误。但即使有了这个修正,我们得到了神秘的虚无。

这个问题的答案隐藏在一个Github问题和EF核心文档中迁移文档的注释中。同样的解决方案解决了我试图在UWP应用程序中使用迁移时遇到的问题(同样,使用一个单独的类库来托管它的DbContext。

我写这篇博文是为了在解决问题之前提出解决方案。

为了从.NET标准库运行迁移,我们在EF Core 1.0中使用的解决方案是针对.NET标准的多目标迁移(因此您可以在几个地方使用该库). net Core(这样就可以运行迁移)。

这意味着更换

         
          
          
           网络标准20
          
         

具有

         
          
          
           netcoreapp2.0; netstandard2.0
          
         

注意,属性名现在是复数,并且在两个sdk之间有一个分号。

但还有一个秘密不在文件中。

对于.NET标准2.0(和EF Core 2.0),您还需要将以下内容添加到csproj。

         
          
           
         

现在将dbContext项目设置为启动,并确保包管理器控制台(或命令行)指向同一个项目,迁移命令将起作用。

感谢Christopher Moffat,他在Github问题中找到了解决方案,并在评论中分享了它。EF核心包管理器控制台工具文件。


托尼的截图……请参阅下面我的评论回复您的评论。

阿姆斯特丹2018欧洲领域驱动设计

我很高兴能在2018年2月1日至2日在阿姆斯特丹参加DDD欧洲2018大会并发表演讲。亚博国际网页很荣幸能和这么多DDD大师以及其他有着惊人DDD体验故事的人一起参加演讲会。

最低的早鸟票价格仍然可以买到截至11月30日,售价为599欧元(增值税+21% =)724欧元(应用程序。$860U+)。票将转到€699(+增值税)从12月1日到12月31日749欧元(增值税)直到会议。

会议开始前,还有10个精彩的研讨会,从1月30日到1月31日的1/2天到2天不等。

在会议期间,我将进行一个2小时的研讨会,讨论如何使用EF Core 2在您的域中映射DDD模式。这将是一个实际操作的研讨会,我的目的是为与会者建立一些Koan。不过,随着我不断渗透想法,动手实践的味道可能会发生变化。

观看我的领域驱动设计基础课程

dbcontext.add-in-efcore(和ddd-win)的另一个用例

如果您像我一样,按照域驱动的设计原则设计类,您可能会发现自己使用这样的代码来控制如何将对象添加到根实体中的集合中。

公共类武士公共武士(字符串名称):this()name=name;私有Samurai () {_quotes=new List
          
           ();}公共int id get;私人设置;}公共字符串名称{get;私人设置;}private readonly list _quotes=new list()private ienumerable quotes=>_quotes.tolist();public void addquote(string quotext)var new quote=new quote(quotext,id);_ QUOTES.ADD(新报价);}
          

我有一个完整的封装了引号的集合。添加新引用的唯一方法是通过AddQuote方法。你不能只调用samura。quote。add (myquote)

此外,因为我想控制开发人员如何与我的API交互,没有用于引号的数据库集。您必须通过context.Samurais执行所有查询和更新。

一个很大的缺点是,如果我有一个新的报价,我知道武士的ID,我必须先查询武士,然后使用addquote。这真让我恼火。我只想创建一个新报价,输入并保存武士的ID值。这需要原始SQL或DbSet 。我两种选择都不喜欢。在这种情况下,原始SQL是一种黑客,dbset 将打开我的API潜在的滥用。

我今天早上躺在床上时想到了这个问题(承认吧,这是你醒来的第一件事,同样,对吗?)有了一个主意。

在英孚的核心,现在,我们可以直接将对象添加到上下文中,而不需要经过DbSet。上下文可以找出实体所属的dbset,并将正确的信息应用到变更跟踪器。我觉得这样打电话很方便

myContext.AddRange (personobjectA会计,产品对象c);

尽管我还没有遇到一个很好的利用它的用例。

我想到的是,如果dbContext.add是使用反射,也许英孚核心能找到一个私有的dBSET

所以我在dbContext类中添加了一个私有dbset:

私有数据库
          
           引文{ get;设置;}
          
并尝试了这段代码(注意,我使用的是context.Add,不是context.Quotes.Add):
静态void addquotetosamurai()使用(var context=newsamuraicontext())var quote=newquote(“voila”,1);context.Add(报价);context.SaveChanges ();}}
并且它成功了!但这还没有完成。我打破了确保只有我的聚合根可以管理报价的规则。所以这是“危险的”从我的DDD角度看代码。然而,我很高兴知道英孚核心将支持这一能力。
目前,samurai.addQuote没有要对报价执行的任何附加逻辑。如果我在简历中加上“删除不好的字眼”会怎么样?报价单添加前的规则?
public void AddQuote (string quoteText){实用程序。removebadwords (quoteText);var new quote=新报价(QuoteText,ID);_ QUOTES.ADD(新报价);}
现在我有了一个重要的理由用武士来做这件事。我可以补充一点,也接受int的静态AddQuote方法。因为它是静态的,这是一种传递方法。
公共静态引号addquote(string quotext,int samuraiid)utilities.removebadwords(quotext);var newQuote = newQuote (quoteText samuraiId);返回newquote;}

这是可行的,现在我不需要有武士的实例来使用它:

staticvoid addquotetosamurai()使用(var context=newsamuraicontext())context.add(samurai.addquote(“static voila”,1));context.SaveChanges ();}

我担心的一件事是,如果我有一个武士的例子,并试图用它来增加一个引用到另一个武士。这将破坏聚合根…它的工作只是管理自己的引用。它不应该知道其他的武士。

但是.NET保护我不受此影响。我不能从武士的实例调用静态方法。

我仍然认为,从DDD的角度来看,这个静态的,在聚合根中的传递方法,因此必须对此进行研究(或者在我的评论中等待任何不满意的ddder)。但现在我很高兴我可以避免为了完成这项任务而去查询武士的实例。

首次进入.NET核心2.0

我必须从某个地方开始,所以我开始用超级婴儿步。下载.NET核心2夜间版本并尝试创建一个简单的控制台应用程序。我马上就惨败了。的原因吗?夜间建造已经完成了!他们正在研究2.1.0,我不小心抓住了它。这对我来说有点太血腥了。

有一个码头工人形象你可以很容易地使用,但我想试试cli,vs代码和Visual Studio。因此,我想把这些比特直接安装到我的机器上。

我将向您展示的是我在MacOS和Windows10上做的第一次测试。我这样做只是为了确保事情运行正常。注意,在MacOS上,我刚在我的计算机上直接安装了这个新版本,在那里我有其他版本的.NET核心。关键是没有依赖于其他版本的生产工作,所以我不会搞砸任何重要的事情。两个版本可以共存。只是对于像我这样“知道足够危险”的人来说,尽管我知道创建本地nuget.config文件以及在global.json中指定版本等技巧,但很容易与版本纠缠在一起。在Windows上,然而,我使用的是一个干净的虚拟机,上面没有其他版本的.NET。不管怎样,这是明智的做法。虽然我尝试了在我的机器上安装它的不明智的方法,它已经有了各种各样的框架版本,甚至我的版本控制技巧,我无法让2.0.0进行还原或生成。

我在上面提到,我最初下载的SDK版本不正确。(请注意,典型的SDK安装还包括运行时…,所以我得到了两者的错误版本。你可以在里面看到血淋淋的细节本期Github我在解决问题时不断更新。)我想坚持使用.NET核心2.0.0。它的安装程序隐藏在github.com/dotnet/cli的一个分支中,而不是从主服务器获取绝对最新的版本。而是转到https://github.com/dotnet/cli/tree/release/2.0.0。有一个坚实的2.0.0版本- 2.0.0-preview2-006391。这是我在Windows和MacOS上使用的。

2017年6月11日\12-23-16.jpg

确保nuget知道在哪里找到包

您可以在创建项目之前更新全局nuget.config。另外,您可以创建一个项目,然后向其中添加一个本地nuget.config文件。

在MAC上,位于[user]/.nuget/nuget的全局配置文件。这是我的截屏,MacOS不是您的主要平台,您仍然在为这些事情而奋斗。

2017 - 06 - 11 - _12 32 - 15. jpg

在Windows中,在%appdata%\nuget\处。

我有一个链接指向配置Nuget行为“当我忘记在哪里找到它时,医生会帮我。

我在PackageSources部分添加了这两个键:


           
           

现在是时候创建一个项目了

我在Mac上,所以,我们将前往终点站。

我创建了一个名为EFCore20的新文件夹——我知道这是。net Core,但最终我也计划在EF Core 2.0中添加。
我的计划是创建一个.NET核心控制台应用程序(这将依赖于NetCoreApp2.0)和一个库。库将基于netstandard2.0库。这意味着我可以从各种各样的应用程序中使用这个库,包括基于。net 4.6.1的应用程序。EF Core 2.0也将依赖.NET标准2.0,所以任何应用程序或API都可以使用NetStandard,也可以使用EF Core 2.0。阅读更多关于这方面的信息 在GitHub上发布EF Core 2.0公告

我为efcore20文件夹中的每个文件夹创建了一个文件夹:

NETCORE2控制台
netstandard2lib

然后我将cd放入netcore2console应用程序中,使用以下命令创建该应用程序:

dotnet新控制台。
就这些。这就创建了一个小小的Hello World应用程序。dotnet new命令还将在创建文件之后执行dotnet还原。这是你第一次看到事情是否会再次好转。如果恢复失败,它会立刻告诉你。
这是我得到的信息时,有东西错位:
错误消息:错误MSB4236:找不到指定的SDK“microsoft.net.sdk”。
“指定”sdk是您所引用的任何sdk的当前安装版本。在我看来,dotnet enw控制台的默认值为“dotnetcore”无论安装的版本是什么,都可以使用该版本。
最有可能的问题是,您没有为dotnet提供正确的URI来查找正确的NuGet包。
如果不想破坏全局配置,您可以使用应用程序在文件夹中创建本地nuget.config文件。整体而言,它看起来像:
           
           
            
             
             
            
           
即使dotnet new将调用restore,我喜欢打电话
网络还原
明确地。(控制狂)
如果恢复正确,那么验证的下一步是
网络建设
希望这也不会给你带来错误。它不应该。
最后,
网络游戏
会导致吐出
你好世界!
现在我知道它起作用了。有点傻,但我想在浪费时间写一堆不会运行的代码之前验证一下,因为我甚至没有正确安装.NET内核。
另一个关注点是dotnet新控制台创建的文件。
如果我把它们打开会更容易看到 Visual Studio代码我可以通过打字
代码。
只有两个文件。包含项目元数据和程序文件的csproj。csproj文件表示目标框架是netcoreapp2.0。

2017 - 06 - 11 - _14 - 09 - 46所示

程序文件启动时只会发出hello world。
2017年6月11日
下面是命令行中所有步骤的屏幕截图 dotnet新主机你好世界!输出包括我的额外 网络还原。我喜欢显式恢复的另一件事是它显示了关于恢复的更详细的信息。
2017 - 06 - 11 - _14 - 03 - 19所示
接下来,我要确保.NET标准库也能正常工作。
仍在终端(或控制台或PS,如果您在Windows上)我现在进入第二个子文件夹,ef core2/netstandard library.dotnet新库默认为对库使用netstandard。所以很容易。
Dotnet新库
创建库并恢复所需的包。
这是这个新库的默认内容,再一次,显示在vs代码中。
Ntice说它的csproj说目标框架是netstandard2.0。 2017 - 06 - 11 - _14 16 - 09年
还有一个空的类文件。
2017 - 06 - 11 - _14 - 18 - 12所示
我将修改类以添加返回字符串的公共方法:“为什么,你好!”
2017年6月11日

现在,我将进入控制台应用程序的csproj,并给它一个库的项目参考。智能感知还没有?帮我做这件事,我的记忆糟透了*,所以我去了奈特·麦克马斯特的Handy Project.json去了CSproj的Mind Mapper,又名project.json到msbuild转换指南提醒自己项目引用的语法。我将其添加到控制台应用程序的csproj文件的属性组部分下面

          
           
          
再次运行dotnet还原和dotnet build将有助于识别您是否有输入错误。我经常这样做。
现在,我将修改Program.cs文件,也调用输出从我的库调用HiYa方法的结果:
2017年6月11日

然后返回到我的终端窗口(尽管我也可以在vs code的内置终端内完成)。我构建了这个库,然后切换到控制台文件夹。重建并运行它…瞧

NETCORE2控制台网络游戏

你好世界!

为什么,你好!

NETCORE2控制台

所以现在我知道.NET核心2(从夜间构建预览)正在我的计算机上正常运行,我可以创建和使用.NET标准2.0库。这意味着我可以继续并自信地开始创建一个.NET标准2.0库来承载一些EF核心2.0逻辑。

我也在我的Windows机器上重复了这整件事。这不仅让我知道我可以在那里使用这个版本的.NET核心,但我也将在Visual Studio中使用. net Core 2.0预览版做一些工作。

*(咄,我应该在vs代码中把自己变成一个片段!)