标签:err googl flow base ast each wpa ica mini
参考页面:
http://www.yuanjiaocheng.net/ASPNET-CORE/first.html
http://www.yuanjiaocheng.net/ASPNET-CORE/asp-net-core-overview.html
http://www.yuanjiaocheng.net/ASPNET-CORE/asp.net-core-environment.html
http://www.yuanjiaocheng.net/ASPNET-CORE/newproject.html
http://www.yuanjiaocheng.net/ASPNET-CORE/project-layout.html
官方资料:
相关文章:ASP.NET 5 RC1 升级 ASP.NET Core 1.0 RC2 记录
ASP.NET Core 1.0 更新比较快(可能后面更新就不大了),阅读注意时间节点,这篇博文主要记录用 ASP.NET Core 1.0 开发简单应用项目的一些记录,以备查阅。
ASP.NET Core 1.0 相关 Nuget 程序包源:https://api.nuget.org/v3/index.json
阅读目录:
参考文章:
在用 ASP.NET Core 1.0 开发之前,理解 .NET Platform Standard(.NET 平台标准)是非常有必要的,因为部署是跨平台的,ASP.NET Core 1.0 应用程序的配置不同,部署环境也会不同,并且项目之间的兼容也会存在一些问题。
.NET Platform Standard 列表(2016 上半年):
| Target Platform Name | Alias | |||||||
|---|---|---|---|---|---|---|---|---|
| .NET Platform Standard | netstandard | 1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 |
| .NET Core | netcoreapp | → | → | → | → | → | → | 1.0 |
| .NET Framework | net | → | → | → | → | → | → | 4.6.3 |
| → | → | → | → | → | 4.6.2 | |||
| → | → | → | → | 4.6.1 | ||||
| → | → | → | 4.6 | |||||
| → | → | 4.5.2 | ||||||
| → | → | 4.5.1 | ||||||
| → | 4.5 | |||||||
| Universal Windows Platform | uap | → | → | → | → | 10.0 | ||
| Windows | win | → | → | 8.1 | ||||
| → | 8.0 | |||||||
| Windows Phone | wpa | → | → | 8.1 | ||||
| Windows Phone Silverlight | wp | 8.1 | ||||||
| 8.0 | ||||||||
| Mono/Xamarin Platforms | → | → | → | → | → | → | * | |
| Mono | → | → | * |
上面图表时间虽然有点老,但和现在的发展是一样的,只不过版本有所更新,主要的三个平台:
我们在开发 ASP.NET Core 1.0 应用程序的时候,一般是选择netstandard或netcoreapp版本,并且这两个平台版本是相互兼容的,分别看一下示例:
netstandard1.6平台:
{
"version": "1.0.0",
"dependencies": {
"Microsoft.EntityFrameworkCore": "1.0.0",
"NETStandard.Library": "1.6.1"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}
"imports": "dnxcore50" 的意思是兼容之前dnxcore50平台(dnxcore50现在已被废弃,并被netcoreapp取代),比如你之前有个类库是用dnxcore50平台开发的,现在使用netstandard平台开发的类库,如果不添加此配置,是会报错的。"NETStandard.Library": "1.6.1"包含了一系列和netstandard相关的 Nuget 程序包,配置netstandard平台,必须添加此配置,如果没有的话,.NET 基础的命名空间是访问不到的。netcoreapp1.1.0平台:
{
"version": "1.0.0",
"dependencies": {
"Microsoft.EntityFrameworkCore": "1.0.0"
},
"frameworks": {
"netcoreapp1.1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.1.0"
}
}
},
"imports": [
"dotnet5.6",
"portable-net45+win10"
]
}
}
}
netstandard1.1.0平台和上面netstandard1.6平台配置差不多,Microsoft.NETCore.App 和 NETStandard.Library 是一样目的,dotnet5.6和dnxcore50一样,都是 .NET Core 之前平台的废弃代号。
portable 的意思是便携型,如果添加了此配置,表示应用程序发布部署不携带依赖的程序包,而是使用系统中安装配置的。
还有一点需要注意的是,netcoreapp1.1.0平台和netstandard1.6平台开发是相互兼容的,比如我们开发一些自己的 Nuget 程序包,使用的平台版本可以是上面两个,但最好是使用netstandard低一点的版本,因为以后netstandard可能是微软平台的一种标准规范,比如我现在开发 Nuget 程序包平台使用netcoreapp1.1.0,ASP.NET Core 1.0 应用程序使用netcoreapp1.1.0平台,后者就可以引用前者,因为第三方 Nuget 程序包使用平台版本可能比较低,所以我们开发的 ASP.NET Core 1.0 应用程序平台版本也相应低一些。
Startup 需要添加额外的配置,以便于单元测试的进行,比如 EF、依赖注入和 AutoMapper 配置,需要独立进行配置,而不是放在 ASP.NET Core 1.0 应用程序中的 Startup 配置中。
比如这样的一个项目 Sample.BootStrapper:
public static class Startup
{
public static void Configure(this IServiceCollection services, string connectionString)
{
services.AddDbContext<SampleDbContext>(options =>
options.UseMySQL(connectionString, b => b.MigrationsAssembly("Sample.WebApi"))
);
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddScoped<IDbContext, CommodityDbContext>();
ConfigureMapper();
}
private static void ConfigureMapper()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SupplierItem, PurchaseItemDTO>()
.ForMember(d => d.ItemDetailDTOs, opt => opt.MapFrom(s => s.SupplierItemSkus));
cfg.CreateMap<SupplierItemSku, PurchaseItemDetailDTO>();
});
}
}
project.json 配置:
{
"version": "1.0.0-*",
"dependencies": {
"System.ComponentModel.Primitives": "4.1.0",
"Microsoft.NETCore.App": ""
},
"frameworks": {
"netcoreapp1.1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.1.0"
}
}
}
}
}
上面代码主要是对 IServiceCollection 的 Configure 方法进行了扩展,这样对 Domain、Repository 和 AppliactionService 进行独立的单元测试了,只需要在构造函数中进行添加调用即可,后面再说这一点。
另外,ASP.NET Core 1.0 应用程序的 Startup 示例代码:
public class Startup
{
public Startup(IHostingEnvironment env)
{
#if DEBUG
var path = Directory.GetCurrentDirectory();
#else
var path = env.ContentRootPath;
#endif
var builder = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Error()
.WriteTo.RollingFile(Path.GetFullPath("logs/log-{Date}.txt"))
.CreateLogger();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// 配置 WebApi 返回 Json 数据大小写问题,默认数据会首字母小写。
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
// 注意这里
services.Configure(Configuration["data:ConnectionString"]);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddSerilog();
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseStaticFiles();
app.UseMvc();
}
}
日志服务使用的是 Serilog,日志级别有多种进行选择(可以 Debug、Error 等),日志和连接字符串的配置可以放在 appsettings.json 文件中,ConfigureServices 里面调用 Sample.BootStrapper.StartUp 的配置。
project.json 示例代码:
{
"dependencies": {
"Microsoft.AspNetCore.Mvc": "1.0.1",
"Microsoft.AspNetCore.Routing": "1.0.1",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Microsoft.Extensions.Logging": "1.1.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Microsoft.AspNetCore.Cors": "1.0.0",
"Serilog": "2.3.0",
"Serilog.Extensions.Logging":"1.3.1",
"Serilog.Sinks.RollingFile": "3.2.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Sample.BootStrapper": "1.0.0-*",
"Microsoft.EntityFrameworkCore.Design": {
"type": "build",
"version": "1.0.0-preview2-final"
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0.1": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": [
"dotnet5.6",
"portable-net45+win10"
]
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"wwwroot",
"**/*.cshtml",
"appsettings.json",
"web.config"
]
},
"scripts": {
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
}
appsettings.json 示例代码:
{
"data": {
"ConnectionString": ""
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Error",
"System": "Information",
"Microsoft": "Information"
}
}
}
另外,在 Program.cs 中可以配置选择服务器,比如 IIS 或 Kestrel 等。
相关文章:
单元测试主要包含两方面:类库项目单元测试和 WebApi 项目单元测试。
类库项目单元测试代码示例:
using Microsoft.Extensions.DependencyInjection;
using Xunit.Abstractions;
using Sample.BootStrapper;
public class UnitTest
{
private readonly ITestOutputHelper output;
private IServiceProvider provider;
private IProductRepository _productRepository;
public UnitTest(ITestOutputHelper output)
{
var connectionString = "";
var services = new ServiceCollection();
this.output = output;
services.Configure(connectionString);
provider = services.BuildServiceProvider();
_productRepository = provider.GetService<IProductRepository>();
}
[Fact]
public async Task GetTest()
{
Assert.True(true);
}
}
provider.GetService 手动获取依赖注入的对象,ITestOutputHelper 的目的是取代Console.WriteLine(因为不支持),但现在 ITestOutputHelper 好像也输出不了,之前 RC2 的时候是可以的,不知道啥原因。
WebApi 项目单元测试示例代码:
using Xunit.Abstractions;
using Microsoft.AspNetCore.TestHost;
using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Sample.WebApi;
public class UnitTest
{
private readonly ITestOutputHelper output;
private readonly TestServer _server;
private readonly HttpClient _client;
public UnitTest(ITestOutputHelper output)
{
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
}
[Fact]
public async Task GetTest()
{
var ids = new List<int>{1, 2};
var httpContent = new StringContent(JsonConvert.SerializeObject(ids), Encoding.UTF8, "application/json");
var response = await _client.PostAsync($"/products", httpContent);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
}
RC2 版本是无法对 WebApi 进行单元测试的,因为 TestHost 不支持,现在 ASP.NET Core 1.0 版本和 ASP.NET WebApi 2 是差不多的了,使用也很方便,不过 HttpClient 没有了 PostAsJsonAsync 方法,需要使用 JsonConvert 手动转换一下。
project.json 配置代码:
{
"version": "1.0.0-*",
"testRunner": "xunit",
"dependencies": {
"xunit": "2.2.0-beta4-build3444",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"Microsoft.AspNetCore.TestHost": "1.0.0",
"Microsoft.Extensions.DependencyInjection": "1.1.0",
"Sample.BootStrapper": "1.0.0-*",
"Sample.WebApi": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0.1": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": [
"dotnet5.6",
"portable-net45+win10"
]
}
}
}
我之前用netstandard1.6平台,但配置 xunit 的时候,发现不支持最新的版本,后来就该用了netcoreapp1.0.1,testRunner 配置后可以在 Test Explorer 窗口中看到单元测试,也可以在方法的窗口上看到,主要用于调试目的。
单元测试命令:dotnet test
Microsoft.EntityFrameworkCore 和 EntityFramework 7 的用法差不多,现在项目使用的 MySql 数据库,示例配置代码:
public class SampleDbContext : DbContext
{
public SampleDbContext(DbContextOptions<SampleDbContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddEntityConfigurationsFromAssembly(GetType().GetTypeInfo().Assembly);
}
}
Map 映射配置(可能多个):
public class ProductMap : EntityMappingConfiguration<Product>
{
public override void Map(EntityTypeBuilder<Product> builder)
{
builder.HasKey(p => p.Id);
}
}
AddEntityConfigurationsFromAssembly 是对 ModelBuilder 的扩展,这样如果有多个实体映射配置,OnModelCreating 中只需要一行代码就可以了,扩展代码:
public interface IEntityMappingConfiguration
{
void Map(ModelBuilder b);
}
public interface IEntityMappingConfiguration<T> : IEntityMappingConfiguration where T : class
{
void Map(EntityTypeBuilder<T> builder);
}
public abstract class EntityMappingConfiguration<T> : IEntityMappingConfiguration<T> where T : class
{
public abstract void Map(EntityTypeBuilder<T> b);
public void Map(ModelBuilder b)
{
Map(b.Entity<T>());
}
}
public static class ModelBuilderExtenions
{
private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
{
return assembly
.GetTypes()
.Where(x =>
!x.GetTypeInfo().IsAbstract &&
x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
}
public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
var mappingTypes = assembly.GetMappingTypes(typeof(IEntityMappingConfiguration<>));
foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>())
config.Map(modelBuilder);
}
}
project.json 示例代码:
{
"version": "1.0.0-*",
"dependencies": {
"MySql.Data.EntityFrameworkCore": "7.0.6-IR31",
"MySql.Data": "7.0.6-IR31",
"System.Reflection.TypeExtensions": "4.3.0",
"Microsoft.Extensions.DependencyInjection": "1.1.0"
},
"frameworks": {
"netcoreapp1.0.1": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
}
}
}
}
EntityFrameworkCore 针对 MySql 微软没有开放相应的 Nuget 程序包,第三方有很多的程序包,但或多或少的有些问题,MySql.Data.EntityFrameworkCore 是 EntityFrameworkCore GitHub Issue 中出现最多的,并且是 MySql 自己开发的,所以使用的话没什么问题。
如果在查询的时候报这个错误:
System.MissingMethodException was unhandled
HResult=-2146233069
Message=Method not found: ‘Void Microsoft.EntityFrameworkCore.Query.QueryContextFactory..ctor(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IStateManager, Microsoft.EntityFrameworkCore.Internal.IConcurrencyDetector, Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeDetector)‘.
Source=Microsoft.EntityFrameworkCore.Relational
StackTrace:
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalQueryContextFactory..ctor(IStateManager stateManager, IConcurrencyDetector concurrencyDetector, IRelationalConnection connection, IChangeDetector changeDetector)
--- End of stack trace from previous location where exception was thrown ---
解决方式是引用 MySql.Data.EntityFrameworkCore 程序包的类库,移除 Microsoft.EntityFrameworkCore 程序包,参考资料:MissingMethodException DbSet.ToList
另外,关于 EntityFrameworkCore 如何记录执行 SQL,Google 找了好久也没找到好的解决方案,最后找到了一个别人写的 IQueryable 扩展方法:
public static class IQueryableExtensions
{
private static readonly TypeInfo QueryCompilerTypeInfo = typeof(QueryCompiler).GetTypeInfo();
private static readonly FieldInfo QueryCompilerField = typeof(EntityQueryProvider).GetTypeInfo().DeclaredFields.First(x => x.Name == "_queryCompiler");
private static readonly PropertyInfo NodeTypeProviderField = QueryCompilerTypeInfo.DeclaredProperties.Single(x => x.Name == "NodeTypeProvider");
private static readonly MethodInfo CreateQueryParserMethod = QueryCompilerTypeInfo.DeclaredMethods.First(x => x.Name == "CreateQueryParser");
private static readonly FieldInfo DataBaseField = QueryCompilerTypeInfo.DeclaredFields.Single(x => x.Name == "_database");
private static readonly FieldInfo QueryCompilationContextFactoryField = typeof(Database).GetTypeInfo().DeclaredFields.Single(x => x.Name == "_queryCompilationContextFactory");
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
if (!(query is EntityQueryable<TEntity>) && !(query is InternalDbSet<TEntity>))
{
throw new ArgumentException("Invalid query");
}
var queryCompiler = (IQueryCompiler)QueryCompilerField.GetValue(query.Provider);
var nodeTypeProvider = (INodeTypeProvider)NodeTypeProviderField.GetValue(queryCompiler);
var parser = (IQueryParser)CreateQueryParserMethod.Invoke(queryCompiler, new object[] { nodeTypeProvider });
var queryModel = parser.GetParsedQuery(query.Expression);
var database = DataBaseField.GetValue(queryCompiler);
var queryCompilationContextFactory = (IQueryCompilationContextFactory)QueryCompilationContextFactoryField.GetValue(database);
var queryCompilationContext = queryCompilationContextFactory.Create(false);
var modelVisitor = (RelationalQueryModelVisitor)queryCompilationContext.CreateQueryModelVisitor();
modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
var sql = modelVisitor.Queries.First().ToString();
return sql;
}
}
调用示例:
var query = _productRepository.Get(1);
var sql = query.ToSql();
Console.WriteLine(sql);
不过暂时只能输出单表查询的,多表关联查询的执行 SQL 输出不了。
相关文章:
相对于 EntityFramework 7,EntityFrameworkCore 迁移改变很多,
首先,ASP.NET Core 1.0 project.json 中添加如下配置:
{
"dependencies": {
"Microsoft.EntityFrameworkCore.Design": {
"type": "build",
"version": "1.0.0-preview2-final"
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0.1": { }
}
}
Sample.BootStrapper.Startup 中 Configure 修改如下:
public static void Configure(this IServiceCollection services, string connectionString)
{
services.AddDbContext<CommodityDbContext>(options =>
options.UseMySQL(connectionString, b => b.MigrationsAssembly("Sample.WebApi"))//添加 MigrationsAssembly
);
///to do...
然后 CMD 直接切换到 Sample.WebApi 文件目录下,执行如下命令:
dotnet ef migrations add 名称dotnet ef database update相关资料:.NET Core 命令行接口工具
dotnet 具有以下命令:
dotnet new:初始化 C# 或 F # 控制台应用程序项目。dotnet restore:还原给定应用程序的依赖项。dotnet build:生成 .NET Core 应用程序。dotnet publish:发布 .NET 可移植或独立应用程序。dotnet run:从源运行应用程序。dotnet test:使用 project.json 中指定的测试运行程序运行测试。dotnet pack:创建代码的 NuGet 包。CLI 还支持持续集成,不过没试过,我第一次用 dotnet pack,结合 Nuget Package Explorer 可以很方便的发布管理程序包。
大概就记录这些。
标签:err googl flow base ast each wpa ica mini
原文地址:http://www.cnblogs.com/liubingbing/p/6343701.html