所有职位由朱莉

在Visual Studio代码中构建基于c#项目的Azure函数

我已经使用了一段时间的Visual Studio代码的Azure函数,它们继续以很好的方式发展。最近的一次换班让我陷入了一个循环,所以我想我会为那些还没有开始的人记录一些。我还应该指出,在过去一年左右的时间里,我一直专注于用JavaScript编写函数,因为我喜欢把事情搞混一点,这也使得与不以.NET为中心的开发人员共享Azure函数更加容易。

我也写过关于在msdn杂志上用vs代码创建Azure函数的文章,但同样,自从我写这篇文章以来,情况就变了。我已经使用了一段时间的版本2 API,所以我没有说话(好吧,写)关于从v1到v2的变化,以及使用Azure函数扩展的体验的变化。

同样值得注意的是,Azure功能团队实际上推荐使用Visual Studio来构建基于c#的应用程序和用于JavaScript的VS代码。但是我经常在我的MacBook上使用vs代码,所以我还是要和c一起走这条路。

在对文档进行了足够多次的重新访问后,最终发现了一些关键信息,我意识到为什么使用c#的扩展会改变这种体验。在此之前,我曾经使用过C脚本函数(.csx),这与您直接在门户中工作时使用的相同。但是扩展模板现在驱动您使用C项目功能,这有很大的不同。c#脚本函数更像javascript函数。它们依赖于手动创建的function.json文件来定义绑定,并可以基于绑定安装适当的扩展包。CSX文件在运行时编译。有了C类库,您可以像开发其他C类库一样进行开发——安装相关的包,然后使用属性将方法标识为Azure函数和触发器,输入和输出绑定。编译库时,Azure函数工具将为您生成一个被部署的function.json文件。

因为我习惯于用javascript或脚本路径创建函数,使用C类库的Azure函数扩展的新默认值确实让我陷入了一个循环。因此,我决定用文档记录在这个工作流程中行走,因为我必须学习它。我想我还是更喜欢重量较轻的C脚本(.csx)或JavaScript流,但这可能与我在许多情况下对vs代码的偏好相一致,而不是Visual Studio。

编写Visual Studio代码

所以首先要做的是:你需要安装天青函数蓝天账户扩展到VS代码,Azure函数扩展依赖于Azure函数核心工具。扩展安装说明将帮助您获得所需的所有内容,扩展会检查更新并提示您根据需要更新这些工具。事实上,我昨晚收到这个提示。2019 - 01 - 16 - _09 - 28 - 10. png

安装了扩展之后,现在是创建一个函数应用程序项目的时候了。您应该已经创建了一个文件夹来存放您的项目,您也可以用VS代码打开它。我的名字叫AzureFunctionProj。

然后你可以点击“创建新项目”功能栏上的图标(当您将鼠标悬停在功能栏上时,图标会显示出来),以便在文件夹中创建新的功能应用程序项目。

2019-01-17_18-11-39.png

工作流的这一部分没有更改。

  1. 它将要求您指向一个文件夹,打开的文件夹应该作为默认选择。
  2. 然后它会让你选择一种你将在应用程序中使用的语言。从选项(c,JavaScriptPython(仍然是预览)和Java(也是预览),我将选择c#。

因此,将使用模板创建新的.NET核心项目,您将在文件夹资源管理器中看到以下内容:

2019-01-17_18-19-58.png

azurefunctionproj文件夹中的所有这些文件都是由模板创建的。最重要的是csproj文件,我在其中突出显示了一些最相关的设置。

         
          
           
            NETCOREAPP2.1
           
           
            
             v2
            
          
          
           
            
          
          
           
            
             保护西部
            
           
           
            
             保护西部
            
            
             从未
            
           
          
         

在函数应用程序中创建一个函数,事情就大不一样了。

你总是从“添加函数”开始偶像2019-01-17 U 18-11-39副本.png

第一步很熟悉,选择功能应位于哪个文件夹中的功能应用程序:

2019-01-17_22-06-37.png

我将选择AzureFunctionProj。

然后有许多触发器模板可供选择,下面的三个选项更有趣:

2019 - 01 - 17 - _16 - 42 - 25. png首先是项目运行时,我肯定想要v2(“~2”)。您可以在功能应用程序中为不同的功能使用不同的语言。这显示了我已经选择的默认值:c#。最后,触发器模板列表过滤为“已验证”。

您可以通过单击这些选项来更改它们。

过滤器选项已验证,核心和所有。核心和所有当前显示相同的列表,其中包括一些额外的预览触发器:DurableFunctionsOrchestration,森德格尔事件hubtrigger和iothubtrigger。

2019-01-17_16-43-20.png

过去我在。net核心函数应用程序中创建JavaScript函数,但现在我将继续使用c#,因为这是真正让我吃惊的地方。我将选择httptrigger,然后系统会提示我提供一个名称。我将保留默认值:HttpTriggerCSharp。然后要求我为将要创建的类提供一个名称空间名称。默认为“company.project”。我将把它改为functiontests.httptest1。要收集的最后一点信息是,您需要为函数选择安全性。选项中,我将选择匿名,因为这是一个演示,我不想处理凭证。

就是这样。将创建函数。

还有一些类库项目的差异

我过去的经验告诉我,在app function文件夹中创建一个新文件夹,里面有函数名,将是函数的类文件和包含绑定配置的function.json文件。类文件在那里(虽然不在它自己的文件夹中)。但是没有function.json文件。还有对我来说很有趣和新鲜的是run方法的functionname属性和run方法签名中httprequest的httptrigger属性。也,我不习惯在使用csx脚本时使用所有这些语句。2019 - 01 - 19 - _15 - 16 - 45. png

在建设项目时,.NET核心读取该属性并构建一个进入bin文件夹进行部署的function.json。2019 - 01 - 17 - _22 - 38 - 03. png

但这不仅仅是熟悉的绑定。注意生成者,配置源,scriptFile和entryPoint标记。

所以第一次装订,httpTrigger绑定,我看起来很熟悉。函数将响应httptrigger。

您可以通过运行或调试来测试这个默认值。奔跑,你可以使用VS Code的CTRL-F5键盘组合,如果您喜欢使用CLI,使用azure函数cli命令:

主机启动

这将运行该函数并提供一个url进行尝试。模板“赌注”方法的编写目的是接受主体中的查询参数或JSON。我将使用一个查询参数:

http://localhost:7071/api/httptriggercsharp?名字=朱莉

以及浏览器输出

2019-01-19_15-57-04.png

将输出绑定添加到
天青宇宙DB

如果我想添加一个输出绑定呢?我习惯通过编辑function.json来实现这一点。但是由于我在属性定义绑定的路径上,我会这样添加绑定。让我们为Azure Cosmos DB添加一个输出绑定。这样,该函数将响应HTTP请求并将一些数据插入Cosmos DB数据库。我已经有一个Azure Cosmos DB账号了,因此,我将定义它以现有帐户中新数据库中的新集合为目标。

为了使用Azure Cosmos DB绑定,我需要将相关包添加到我的项目中。因为我使用c#类库来构建函数,我可以这样做,就像我对任何其他Nuget包…直接添加到csproj或添加包与dotnet核心CLI:

但是现在我正在编写一个c#类库,这样我就可以使用dotnet CLI添加包,或者手动将它添加到.csproj中。我将使用cli:

dotnet添加包microsoft.azure.webjobs.extensions.cosmossdb--版本3.0.3

注意,如果我使用javascript或c脚本构建函数,我需要使用CLI (func extensions install -p)工具注册这个包包装名

现在这个包在csproj中:

          
           
            
           
          
恢复后,我可以添加输出绑定。当前默认函数是异步的,不能向异步方法添加参数。返回值是一种选择。见 https://docs.microsoft.com/en-us/azure/azure函数/函数使用函数返回值触发绑定详情。ICollector或IAsyncCollector是另一个( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet类库写入多个输出值
但是我将使Run方法同步并创建一个输出参数。就像触发器绑定参数一样,我需要向输出参数添加一个属性来指定绑定。我还为数据库和集合名提供参数,具有到数据库帐户的连接字符串的设置的名称,以及最后一个确保在需要时创建数据库和集合的设置。
[FunctionName("HttpTriggerCSharp")]公共静态ActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous,“得到”,“文章”,HttpRequest req,[CosmosDB(数据库名:“CSharpDatabase”,collectionName:“CSharpCollection”,connectionStringsetting=“mycosmosdbconnection”,createifnotexists=true)]out动态文档,ILOGER日志
我添加了mycosmosdbconnection,它是在local.settings.json文件中定义的:
{“IsEncrypted”:假的,“values”:“azurewebjobsstorage”:“”,:“FUNCTIONS_WORKER_RUNTIME dotnet”,“mycosmosdbconnection”:“这是连接字符串的位置“}
注意,如果您使用Azure Cosmos DB触发器创建一个新函数,工具会提示您输入所有相关的数据库信息,在函数代码中包含一个属性,并将其添加到function.json中。
现在只有最后一块拼图了。函数期望我为文档变量提供一个值,然后绑定将该值插入到数据库中。完整的类列表在下面,其中用名称和添加的属性填充文档的单行以红色突出显示。函数和绑定将完成其余的所有工作。
使用系统;使用Microsoft.AspNetCore.Mvc;使用Microsoft.Azure.WebJobs;使用Microsoft.Azure.WebJobs.Extensions.Http;使用Microsoft.aspnetcore.http;使用microsoft.extensions.logging;命名空间函数tests.httptest1公共静态类httptriggercsharp[函数名(“httptriggercsharp”)]公共静态操作结果运行([httptrigger(authorizationlevel.anonymous,“得到”,“文章”,route=null)]httprequest req,[CosmosDB(数据库名:“CSharpDatabase”,collectionName:“CSharpCollection”,connectionStringsetting=“mycosmosdbconnection”,createifnotexists=true)]out动态文档,ilogger log)log.loginformation(“C HTTP触发器函数处理了一个请求”);string name = req.Query["name"];document=新建name=名称,添加=datetime.now;返回名称!= NULL?(actionresult)新的OkObjectResult($你好,name”):new badRequestObjectResult(“请在查询字符串上传递名称”);} }
根据我之前手工配置function.json的经验,我希望在建造之后,bin文件夹中包含cosmossdb输出绑定信息的function.json,但没有。再一次,这是由于JavaScript/ c#脚本函数和c#库函数之间的差异造成的。
在VS代码中,我可以运行或调试函数。调试是F5或调试图标。奔跑,如果没有调试,您可以使用ctrl-f5或tools cli命令:
主机启动
使用cli命令时,我在测试中发现我使用的版本似乎需要我运行 清洁网首先是成功。ctrl-f5为您完成这一步。我在现有的Github发行版中注意到了这一点。你可以读到 在这里.
官方文件中有很多有用的信息。我靠的两个是:

感谢微软颁发的第16届MVP

15年前,7月1日,2003年,我在邮件里收到一个惊喜。一个带着这张纸的信封欢迎我参加微软MVP项目,感谢我在过去一年里在社区里所做的一切。信不信由你,第一个奖项是由微软的学者发起的,因为我和INETA一起做的一件事就是和大学生一起工作。

那张纸刚从信封里拿出来,我跳进车里,开了15英里到我丈夫正在屋顶上工作的工地,让他从屋顶下来让我给他看。我很兴奋也很惊讶。即使这封信并没有完全脱口而出,如果有人像MVP这些天那样联系我填写表格,我相信我也会感到惊讶和兴奋。

从那以后,我很荣幸每年7月1日都能获得这个奖项,因为我做了很多事情,试图通过分享我所学到的知识来缩短其他程序员的学习曲线。我不认为这个奖是理所当然的。我只是跟着我的心做我想做的事情,如果这恰好是他们在做评估时想要的,那我很感激你的特别认可。

我知道这是一个艰难的星期很多长期MVP的不是re-awarded今年的MVP领导(又名社区项目经理(又名CMPs))他们把每一个私人电话的MVP,试图让他们知道尽可能的轻。鉴于此,我非常感谢继续参与2018年7月至2019年6月期间的计划。

在ef core 2.1中定义定义查询

我不得不从我为杂志写的一篇太长的文章中剪下一些文字(发表时的链接),下面是一个简单的例子,使用新的ToQuery方法在EF Core 2.1(目前在预览2中)中创建一个定义查询。

ToQuery与新的查询类型功能它允许您使用未映射到数据库中表的类型,因此这些类型不是真正的实体,不需要密钥,也不跟踪更改。

我从一个包含这两个实体的简单模型开始,映射到我的DbContext中的表。

公共类团队公共int团队id get;设置;}公共字符串名称{get;设置;}公共字符串twitteralias get;设置;}公众名单成员获得;设置;}}公共类TeamMember {public int TeamMemberId {get;设置;}公共字符串名称{get;设置;}公共字符串角色get;设置;}public int teamid获取;设置;}公共时间跨度,典型时间间隔获取;私人设置;}公共void计算通勤时间(datetime start,datetime end)typicalcommutetime=end.subtract(start);}

您需要预先定义用于定义查询的类型,我的将为团队成员提供姓名和典型的工作时间。

公共类团队通勤公共团队通勤(字符串名称,通勤时间){Name = Name;typicalcommutetime=通勤时间;}公共字符串名称get;设置;公共时间典型的通勤时间;设置;}

您可以直接在OnModelBuilding中使用原始SQL和FromSQL,或者在名为ToQuery的新方法中使用Linq查询来定义查询。下面是一个使用定义查询和Linq的查询类型的例子:

modelBuilder.Query
          
           ()
          ToQuery(())>团队成员。选择(m=>新建团队通勤(m.name,m.典型时间)

在teamcomment类上定义了这个查询,现在可以在代码中的查询中使用它,例如:

var comments=context.query ()

请记住,不能同时在同一类型上定义ToQuery和ToView映射。

新的多元化课程!EF核心2:开始

我最近在Pluralsight.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核心工作原理
从ef6到ef core到ef core的路径
EF核心2的新功能
展望英孚核心2.1及更高版本
审查和资源

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

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

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

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

使用该门户复制Azure功能应用程序,Github和云壳

我有一个Azure函数应用程序,其中有一些函数是我为一个会议会议的演示构建的。我在AngularMix首次使用它,并命名了函数应用程序AngularMix12017。上个星期我在Devintersection做的时候,我将其重新创建为devintersection2017,因为您不能重命名函数应用程序。下周我将在另一个会议(netconf.co)上再次这样做,并决定是时候创建一个可重用的名称:dataapidemo。

如果你严格地在门户网站上工作(这就是我在构建功能应用程序的第一个学习阶段的工作方式),你就不能简单地复制一个功能应用程序。你可以很容易地复制它下载和上传它再次。

请记住,如果您在VS 2017或VS Code(结合Azure CLI)中开发函数,您可以使用该工具发布函数应用程序和设置。但是我不喜欢走捷径。走这条路,我学到了很多新的技巧和工具。即使我在下一轮使用工具,我学到了很多,这让我对整体有了更好的理解,更多的控制和故障排除技能。

我的第一步是创建新的函数应用程序(dataapidemo)。

Azure功能应用程序的概览blade有一个“下载应用程序内容”选择权。这将把所有相关文件拖到您的机器上。所以接下来,我进入devintersection2017功能应用程序概述,点击下载应用程序内容链接。

下载app内容时,您还可以选择获取应用程序设置。我的设置中存储了许多秘密…比如数据库的密钥,帐户ID等。如果你检查一下,设置将下载到本地设置文件。如果您使用此功能在本地继续开发,如。在VS2017中,那你就要它们了。但在我看来,它们是没有用的,甚至可能是一个安全问题(您很快就会看到),所以我将不检查它。

我可以看到我电脑上指定文件夹中的文件。

我已经创建了一个Github存储库来存储这些文件:https://github.com/julielerman/DataApiAzureFunctions。

在新文件夹的命令行中,我将初始化,将所有文件添加到本地repo并提交它们。然后我可以运行git命令将该文件夹连接到我的GitHub repo,然后将我的本地存储库推入在线存储库。

完成后,这些文件都在我的Github报告中。

因为我使用的是公共存储库,这就是为什么我不想下载包含我的秘密的local.settings.json文件的原因。当然,我可以在本地删除它,或者让git忽略该文件。关于这点还有几点。如果我是在本地开发的,然后,我可以在本地拥有该文件,并使用VS2017或Azure CLI工具将我的应用程序连同设置发布到门户。但这不是我的目标。

现在,我可以利用Azure门户的一个长期特性:将它连接到一个存储库,以便从存储库自动部署到我的应用程序(在我的函数应用程序中)。

回到入口,我再次选择新的功能应用程序,然后从它的平台功能页面,打开部署选项。选择“设置新部署”,然后按照步骤将功能应用程序连接到存储库。完成设置后,可以使用“同步”按钮强制进行部署。所有文件现在都在我的新dataapidemo函数中,包括包含函数设置的function.json文件(例如以及我可能添加到函数中的任何其他文件。

因为我用的是暮光,我的一个函数在project.json文件中引用了twilio,我需要将这个包恢复到这个函数应用程序中。我通过打开project.json并对其进行一个小的修改来做到这一点……添加或删除一行空白,然后保存它。这将触发包还原。

但是,功能应用程序设置不存在。这些设置是为应用程序定义的,并由一个或多个函数使用。Azure创建了一些默认设置,但我也有一些其他的……例如账户和电话号码为我的暮光积分以及关键的功能。

其中一些设置是我自己的自定义设置,我希望在新函数中使用这些设置。我可以通过门户应用程序设置界面添加它们,但我不喜欢我有一系列设置的路径。

这意味着我们将继续使用另一个在Azure门户网站上令人惊叹的工具——云外壳。在这里,您可以直接在订阅中的服务上运行Azure CLI中的Bash或Powershell命令。您还可以在您的机器上本地执行此操作,但要注意,您必须在那里提供凭证和其他元数据。

在门户,打开云壳。这是一个交互式终端窗口。

如果您有多个订阅,您需要确保它设置为存储应用程序功能的位置。

您可以通过列出订阅AZ帐户列表命令。

如果你想要的不是默认值,然后设置为:

az帐户集-s[id]

这个外壳可以自动完成,所以如果ID以A123开头,你可以输入

AZ账户集-S A123

然后点击标签,ID就完成了。按Enter,它将成为默认的工作订阅。

我将使用Azure函数应用程序命令将设置导入我的函数应用程序。

首先,我将列出现有的设置。你用命令来做这个

az functionapp config appsettings list--名称[功能名称]--资源组[资源名称]

名称和资源组的参数快捷方式为-n和-g。我的都是同一个名字:dataapidemo。以下是命令的外观(除了我的博客强制的包装):

az函数app config appsettings list-n dataapidemo-g dataapidemo

默认情况下,appsettings以JSON形式列出,不过您可以这样做使用输出参数影响输出格式.

我需要查看从其他功能应用程序复制的设置,以便运行:

az函数app config appsettings list-n devintersection2017-g devintersection2017-o tsv

它给了我从中选择设置的列表。

除了列出设置之外,您可以使用设置动词和删除方式删除动词。两者都可以代替动词列表.

通过将set命令和–settings参数组合使用set。在-settings参数之后,可以使用此格式列出一个或多个设置:

az函数app config appsettings set-n dataapidemo-g dataapidemo--settings“property1name=value”,“property2name =值”

请注意,这是在博客文章中包装的,而不是在shell窗口中。

所以我添加了一些我想要添加的设置,看起来更像:

az函数app config appsettings set-n dataapidemo-g dataapidemo--settings“twiliosid=myvalue”,“twilioaccount=myvalue”

我还得补充一些。例如,我的函数需要知道如何访问我的cosmos-db文档数据库,所以它有一个设置,使用db name作为属性名,dbs account endpoint作为值。

一旦我做到了,我能够摆脱为每个会议命名的功能应用程序,使用一个通用的应用程序,不管我在哪里共享它。

我学到了很多新东西!

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

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

public class Samurai {public Samurai (string name): 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.quotes.add(myquote)。

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

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

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

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

myContext.addRange(个人对象,会计,产品对象c);

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

我想到的是,如果dbContext.add是使用反射,也许EF Core可以找到a私有的dBSET

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

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

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

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

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

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

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

第一次进入。net Core 2.0

我必须从某个地方开始,所以我开始用超级婴儿步。每晚下载。net Core 2构建并尝试创建一个简单的控制台应用程序。我马上就惨败了。的原因吗?夜色中的建筑已经跃过鲨鱼!他们正在研究2.1.0,我不小心抓住了它。这对我来说有点太血腥了。

有一个码头工人形象你可以很容易地使用,但我想试试cli,vs代码和Visual Studio。所以我想把钻头安装在我的机器上。

我将向您展示的是我在MacOS和Windows10上做的第一次测试。我这样做只是为了确保事情运行正常。注意,在MacOS上,我刚刚在我的机器上直接安装了这个新版本,其中有其他版本的。net Core。关键是不存在依赖于其他版本的生产工作,所以我不会搞砸任何重要的事情。两个版本可以共存。只是对于像我这样“知道足够危险”的人来说,尽管我知道创建本地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-预览2-006391。这是我在Windows和MacOS上使用的。

2017 - 06 - 11 - _12 23 - 16. jpg

确保nuget知道在哪里找到包

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

在Mac上,位于[user]/.nuget/nuget的全局配置文件。这是一张截图,如果像我一样,MacOS不是您的主要平台,您仍然在为这些事情而奋斗。

2017年6月11日\12-32-15.jpg

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

我有一个链接到"配置NuGet行为”医生,当我忘记在哪里能找到它的时候。

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


           
           

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

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

我创建了一个名为EFCore20的新文件夹——我知道这是。net Core,但最终我也计划加入EFcore2.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控制台
网络标准2LIB

然后我将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 Core。
另一个关注点是dotnet新控制台创建的文件。
如果我把它们打开会更容易看到 Visual Studio代码我可以打字吗
代码。
只有两个文件。带有项目元数据和程序文件的csproj。csproj文件表示目标框架是netcoreapp2.0。

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

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

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

          
           
          
再次运行dotnet restore和dotnet build将有助于确定是否存在拼写错误。我经常这样做。
现在,我将修改program.cs文件,并从我的库中调用输出calling hiya方法的结果:
2017年6月11日

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

γNETCORE2控制台网络游戏

世界你好!

为什么,你好!

γNETCORE2控制台

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

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

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

mashup:Linux上的SQL Server,Mac上的Docker,带有Visual Studio代码

我在Visual Studio代码的新mssql扩展中获得了很多乐趣。我有一篇文章即将在《MSDN》杂志上发表,我也在计划更多的乐趣。我最新的实验是做一个大的mashup,利用了现在有一个Linux版本的SQL Server这一事实。因此,我们不再局限于在Windows或Azure上托管它。在Linux上宿主SQL Server的最轻量级方法是在Docker容器中。当我坐在一台MacBook前打字时,我决不会放弃我的Windows开发或Windows机器。我只是很高兴我有更多的选择,以及有能力分享我正在学习的工作以外的Windows开发人员的世界。

容器不是有状态的。有很多方法可以解决这个问题(我将在下面向您展示),但是我只知道在这里很危险。这是一种在设计时使用SQL Server的好方法。在制作中使用这个是完全不同的故事,在使用这个选项之前,您需要做更多的研究和灵魂探索。

另一方面,有些人确实有这个特定的目标:

为了做到这一点,我必须查阅大量的文档,当然,即使是我可以使用的那些资源,我也会陷入困境。因此,我将分享如何使这个设置工作的完整路径。

先决条件

我的MacBook上已经安装了Docker for Mac。这里是安装链接如果需要执行该步骤。请记住,您不能在虚拟机上执行此操作。我试着用一个干净的设置重复这个过程。

确保Docker设置为至少使用4GB内存。

2017年4月7日\U 13-55-27.jpg

获取SQL Server Docker映像

这就是使整个事情变得如此简单的原因!微软已经创建了一个官方的Docker镜像,上面已经有用于Linux的SQL Server。

在终端窗口中,您可以使用

sudo docker pull Microsoft/MSSQL服务器Linux

一旦安装,“docker images”命令将显示该图像现在在您的计算机上可用。

2017年4月7日

虽然我今天才安装,你可以看到我正在使用的图像-这是最新的版本-是由微软3周前创建的。

从图像中旋转一个(或两个)容器

现在Docker意识到了这个图像,您可以从中创建一个容器——它正在运行映像的实例。

因为我们在Mac上等待一个“bug”固定,我们将实际创建两个容器。

根据你对码头工人的熟悉程度,您可能知道,也可能不知道容器不是有状态的。一旦删除容器,都不见了!如果你在那个容器中保存了数据,它,同样,都消失了。然而,Docker有一个名为“volume”的特性这是在docker实例之间保留状态的一种方法。所以当一个实例关闭时,状态存储在卷中。当打开另一个容器实例时,该卷向容器提供上一个实例的状态。这就是如何使用数据库容器的方法。

下面是一个关于卷的很好的教程:https://rominirani.com/docker-tutorial-series-part-7-data-volumes-93073A1B1B5B72
官方文件:https://docs.docker.com/engine/tutorials/dockervolumes//creating-and-mounting-a-data-volume-container

但是,在托管SQL Server Linux映像的Mac上,Docker存在一个问题(看起来解决方案即将到来)。这会阻止我们以简单的方式使用卷进行持久化。所以,相反,我们将创建一个单独的容器,它是一个“数据卷容器”,然后,我们将把运行SQL Server的容器指向数据卷容器。

创建卷容器

我将命名我的mssqldata。这是创建它的命令。(不要错过命令的完整长度!)

docker create-v/var/opt/mssql--name mssqldataMicrosoft/MSSQL服务器Linux/bin/true

此卷容器仍然使用图像作为其基础。但我们不会从此实例运行SQL Server。

创建SQL Server容器

现在,您可以创建一个容器,在其中运行SQL Server,该容器将使用数据卷容器来保存数据。

docker run-e'accept_eula=y'-e'sa_password=passw0rd'-p 1433:1433--来自mssqldata-d的卷--名称SQL Server Microsoft/mssql Server Linux

需要两个环境变量(accept_eula和sa_password)。用户ID是(gulp)“sa”。密码要求是:“至少8个字符,包括大写字母,小写字母,以10为基数的数字和/或非字母数字符号。我的真是太花哨了!

一旦这些存在,

码头工人

只显示常规容器。卷容器是隐藏的,因此您需要

码头工人PS-A

看到它。

2017 - 04 - 07 - _16 - 07 - 49. - jpg注意,我将运行SQL Server的容器位于端口上,而数据卷容器具有不同的状态“Created”,不会暴露在端口上。

从SQL命令行测试连接

你不必这么做,但这让我很开心,也很有趣。您知道可以通过命令行与SQL Server交互吗?这些工具安装在容器内,但使用起来很麻烦。直接将它们安装到您的计算机上更容易。Mac的命令行工具是SQL CLI.

注:5月16日微软发布了macOS版本的sqlcmd和bcp(批量复制)。很高兴知道您是否已经熟悉sqlcmd。这是他们的博文,有更多的细节。

您可以通过以下方式安装:

NPM安装-G SQL CLI

用mssql命令启动它。

最低限度地说,您需要连接来标识服务器(默认情况下,该服务器位于本地主机上,您不需要指定端口)和密码。它将假定sa为userid。

mssql-s本地主机-p passw0rd

如果成功的话,你会得到一些信息,然后有一个新的提示,MSSQL。

正在连接到本地主机…完成0.4.14 sql-cli版本输入“帮助”使用提示。MSSQL

够了。现在我可以使用我最喜欢的新工具了。这个mssql扩展在Visual Studio代码中.

在Visual Studio代码中连接

一旦在vs代码中安装了mssql,您可以先创建一个新的SQL文件。或者通过命令(命令pallete的f1,MS SQL查看命令,然后查看新查询。这将提示您一次连接一个参数。您还可以从MS SQL Connect命令(C)开始。扩展将提示您输入每个参数。

服务器名称:本地主机数据库名称:(输入)用户名:sa密码:passw0rd保存密码(是或否)配置文件名称:【您的选择】

如果输入正确,它不仅能连接,但详细信息将作为连接配置文件存储在vs代码设置中,并可用于后续的连接。

您可以在连接时以及在IDE右下角连接时看到连接状态。

2017年4月7日\u 18-19-37.jpg

在编辑器中打开的SQL文件中,您可以键入SQL并查看一些现有的代码片段,还可以从IntelliSense获得帮助,IntelliSense已经读取了服务器上的数据架构。到目前为止还没有多少。

选择sqllistdatabases片段,然后执行它(右键单击上下文菜单上的执行查询或e)显示数据库:

2017年4月7日\u 18-22-45.jpg

现在你可以使用TSQL创建数据库,数据库对象,查询数据。在结果窗格中,您将看到数据作为一个网格,类似于您在SSMS中可能看到的网格。您还可以将结果导出到csv或json。我最近写了一篇关于你可以用mssql做的所有很酷的事情的文章,将在2017年6月的MSDN杂志上发表。但是它连接到一个SQL Azure数据库。与此同时,您可以直接进入扩展的文档(aka.ms/mssql-marketplace)。

创建数据库和表

我让更多的代码片段帮助我创建一个数据库和一个表。

第一个是sqlCreateDatabase,我在其中更改了代码段的数据库名称plachholder,创建了一个名为linuxreally的新数据库,然后用e执行该数据库。

重新运行select name from sys.databases命令表明新数据库现在在列表中。

接下来,我利用sqlCreateTable片段来帮助我创建一个新表。我命名了teh table databasesiknow并给它三列

创建表dbo.databasesiknow(id int非空主键,--主键列databasename[nvarchar](50)不为空,知道[位];

出于某种原因,当我创建这个时,智能感知缓存没有自动刷新。可能是因为它是一个新的数据库。甚至mssql扩展的refresh intellisense cache命令也没有启动它。我通过这次断开和重新连接选择linuxreally数据库而不是让扩展在默认情况下连接到master来工作。当我这样做的时候,我可以看到消息“正在更新智能感知……”在状态栏中。在我做完这些之后,每当我修改数据库架构时,IntelliSense都会自动刷新。

一旦我有了新的数据库,我可以执行“从dbo.databasesiknow选择*”看看正确的结果。在我看来,因为我没有添加数据,没有争吵。但很明显它是从我的桌子上读出来的。

2017年4月8日

取下sql-server容器

现在是大型docker卷测试。我第一次从数据库断开连接在VS代码与⇧⌘E。然后我停止并用以下两个命令删除了SQL Server容器:

Docker停止SQL Server Docker RM SQL Server

但我让数据卷容器(mssqldata)继续运行。

然后,我使用与前面相同的命令创建了一个新的容器实例:

docker run-e'accept_eula=y'-e'sa_password=passw0rd'-p 1433:1433--来自mssqldata-d的卷--名称SQL Server Microsoft/mssql Server Linux

在VS代码中,我认为重新连接到服务器和我的新数据库很容易,因为它已经存储在连接配置文件中。这是第一个,本地主机:linuxreally。

2017年4月8日

连接成功,列出的数据库显示了我的新数据库SikNow数据库。从显示模式的数据库中选择*。因此,即使我杀死并重新创建了SQL Server容器,我的数据库仍然保存在数据卷容器中。

下一个测试:取下两个容器。

现在是时候看看当我停止并移除两个容器时会发生什么了!

Docker停止SQL ServerDocker RM SQL服务器Docker停止MSSQLDataDocker RM MSSQLData公司

接下来,我使用与前面相同的命令重新启动sql-server容器,并使用参数来使用(未运行)mssqldata卷容器。

docker run-e'accept_eula=y'-e'sa_password=passw0rd'-p 1433:1433--来自mssqldata-d的卷--名称SQL Server Microsoft/mssql Server Linux

失败了。我需要首先运行数据卷容器。不幸的是,我为此重新运行了create命令并覆盖了现有的容器,所以一切都失去了。好教训!

所以我从零开始。在全新的数据卷容器中,我重新创建了数据库和表。

经过更多的实验,我意识到我误解了关于卷的码头工人文件。您可以创建数据卷容器的副本并删除这些副本。但是你需要成为一个码头忍者。虽然你可以制作容器的各种副本,一旦你找到所有相关的卷,它不见了。这篇博客文章澄清了一些我对WRT创建/备份/恢复数据卷容器仍感到困惑的信息:tricksofthetrades.net/2016/03/14/docker-data-volumes./.

所以底线是您需要让数据卷容器以某种格式(原始的或复制的某种风格)运行。(我仍然很难相信它没有以某种方式存储为一个文件,您可以重新运行,所以只要有人纠正我,我就会更新它!)

窗户,雨衣,LinuxAzure和Anwhere可以承载Docker容器

如果你认为这只是在OSX上做的一些事情(因为这就是我要做的)……不不不!你知道吗现在是Windows的Docker?而vs代码是跨平台的?这是在开发环境中快速启动和运行SQL Server的好方法。

2017年4月8日\U 10-49-59.jpg

正如我在Twitter上说的,将拉取Docker映像和旋转容器的经验与在Windows上安装SQL Server的经验进行比较如下:

在Visual Studio 2017中克隆Github repo…和测验

在我们的VTDOTNETmeetup,我在最后一刻决定演示从GitHub克隆存储库的能力。然后我想我会把它和我计划演示的其他东西结合起来。

我的Github账户中已经有了正确的回购。一个小型ASP.NET核心项目,它是用Visual Studio 2015构建的,使用project.json作为元数据。这是https://github.com/julielerman/NetCoreSolutionToMigrateToVS2017。

我的笔记本电脑上已经有了同样的解决方案,可用于另一个演示:展示vs2017自动迁移基于project.json的解决方案到新的基于csproj的.NET核心项目格式的能力。

聪明的我,我决定一石二鸟。克隆repo并在它打开该解决方案时运行迁移。

因此,我启动了Visual Studio 2017(因为我想展示它有多快),并开始了从我的Github repo克隆解决方案的过程。我已经设置好了我的证书,可以去存档了,从源代码管理打开。

2017年3月21日

这将打开团队资源管理器窗口,我单击了克隆选项,然后打开一个窗口,显示我所连接的所有帐户。

2017年3月21日

我扩大了自己的账户,向下滚动到我想要的回购,选择它并单击Clone按钮。

2017年3月21日

解决方案被克隆,然后在Visual Studio中打开。

2017年3月21日

但它从未触发迁移!如果你看一下解,您可以看到我展开的项目仍然有它的xproj文件和project.json文件。当时我很困惑,但现在我知道发生了什么,为什么没有迁移的答案在解决方案资源管理器的屏幕快照中非常明显。然而,其中一个开发人员正在观看这部影片,刚刚用Visual Studio 2017完成了另一个演示,很快就发现了问题。

让我们继续寻找更多的线索。

我封闭了解。然后从文件/打开,我浏览到它保存在我电脑上的地方,并选择要打开的SLN文件。这次,同样的解决方案在2017年的VS2017中出现,确实触发了移民,很明显,多亏了这个屏幕。

2017 - 03 - 21 - _22 18 - 17所示

然后我让迁移特性完成它的工作。当它完成时,您可以看到项目不再有xproj和project.json文件。

2017 - 03 - 21 - _22 - 21 - 42

现在,看看这个新的解决方案资源管理器屏幕截图与前一个相比。

然后看看新的VS2017特性的列表下的发行说明(https://www.visualstudio.com/en-us/news/releasenotes/vs2017-relnotes)节中IDE,看看你可以告诉什么克隆不同当打开解决方案不仅仅是打开直接从驱动解决方案。

也,我将通过设计或者可能的行为来发现这是否可以被修改为我所期望的行为方式。.

DotNet核心版本混乱

我看到很多人对此摸不着头脑,所以我把它扔在这里,尽管我确信它已经在很多地方被陈述过了。

当您在dotnet命令行(即cli-aka命令行界面)并键入“dotnet”时,将显示运行时的版本。

当您添加版本参数(“dotnet–version”)时,它将返回您正在使用的sdk版本(aka cli aka command line interface)。

下面是一个例子:

如果你感到困惑,你不是一个人。关于如何在dotnet–version应该显示什么?