《在ASP.NET Core中使用Apworks快速開發數據服務》一文中,我介紹瞭如何使用Apworks框架的數據服務來快速構建用於查詢和管理數據模型的RESTful API,經過該文的介紹,你會看到,使用Apworks框架開發數據服務是何等簡單快捷,提供的功能也很是多,好比對Hypermedia的支持,以及提供豐富的異常信息和調用棧信息。另外,Apworks數據服務能夠支持各類類型的倉儲(Repository)實現,在該文的案例中,我使用了MongoDB做爲倉儲的實現,這是爲了快速方便地演示數據服務的搭建過程。若是你所使用的是關係型數據庫,也沒有關係(意思是沒關係,不是說數據沒有關係。。。-_-!!!),基於Entity Framework Core的倉儲實現可以知足你的需求。html
在之前老版本的Apworks中,倉儲的接口是支持飢餓加載的,也就是說,在延遲加載被啓用的時候,倉儲容許經過顯式指定一系列的對象屬性,當主對象被返回時,這些屬性所指向的子對象也會同時返回。這樣的設計在當時的場景下是合理的,由於是否須要加載某些屬性是能夠在程序中指定的,對於相似MongoDB的倉儲實現,它沒有延遲加載的概念,所以能夠忽略這個參數。在Apworks數據服務中,因爲倉儲的操做會直接被DataServiceController調用,而相關的查詢條件都是來自於RESTful API的,所以,很難在API的層面來肯定某些聚合的對象屬性是否須要飢餓加載(Eager Loading)。另外一方面,禁用延遲加載又會產生性能問題,所以,在當前版本的實現中,我尚未考慮好用何種方式來解決這個問題。或許能夠經過HTTP Header來指定須要飢餓加載的屬性路徑,但這是另外一個問題。總之,在接下來的案例中,你將看到,雖然數據已經添加成功,但在返回的結果裏,被聚合的子對象將沒法返回。我會設法解決這個問題。git
假設咱們須要使用Entity Framework快速構建一個支持增刪改查操做的數據服務(Data Service),並但願該服務可以在容器中運行,咱們能夠首先新建一個ASP.NET Core的應用程序,而後依照下面的步驟進行:github
public class Address { public Guid Id { get; set; } public string Country { get; set; } public string State { get; set; } public string City { get; set; } public string Street { get; set; } public string ZipCode { get; set; } } public class Customer : IAggregateRoot<Guid> { public Guid Id { get; set; } public string Name { get; set; } public string Email { get; set; } public Address ContactAddress { get; set; } }
public class CustomerDbContext : DbContext { public DbSet<Customer> Customers { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Customer>() .ToTable("Customers") .HasKey(x => x.Id); modelBuilder.Entity<Customer>() .Property(x => x.Id) .ForSqlServerHasDefaultValueSql("newid()"); modelBuilder.Entity<Customer>() .Property(x => x.Name) .IsUnicode() .IsRequired() .HasMaxLength(20); modelBuilder.Entity<Customer>() .Property(x => x.Email) .IsUnicode() .IsRequired() .HasMaxLength(50); modelBuilder.Entity<Address>() .ToTable("Addresses") .HasKey(x => x.Id); modelBuilder.Entity<Address>() .Property(x => x.Id) .ForSqlServerHasDefaultValueSql("newid()"); base.OnModelCreating(modelBuilder); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Server=localhost\sqlexpress; Database=CustomerService; Integrated Security=SSPI;"); } }
Add-Migration InitialCreate Update-Database成功完成這一步驟後,咱們的數據庫就已經準備好了。事實上,以上步驟都是開發一個Entity Framework Core應用程序所必須經歷的標準步驟,目前尚未用到Apworks的功能(固然,將Customer定義成聚合根除外)。接下來,咱們開始實現並配置Apworks數據服務,接下來的步驟跟基於MongoDB的實現很是相似。
public class CustomersController : DataServiceController<Guid, Customer> { public CustomersController(IRepositoryContext repositoryContext) : base(repositoryContext) { } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc(); services.AddScoped<CustomerDbContext>(); services.AddApworks() .WithDataServiceSupport(new DataServiceConfigurationOptions(sp => new EntityFrameworkRepositoryContext(sp.GetService<CustomerDbContext>()))) .Configure(); } // 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.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.EnrichDataServiceExceptionResponse(); app.UseMvc(); }
下面,咱們來測試一下這個Apworks數據服務。在Visual Studio 2017中按下Ctrl+F5,直接運行ASP.NET Core應用程序,使用你喜歡的RESTful客戶端軟件,向/api/Customers進行POST操做,能夠看到,Customer能夠被成功建立,Customer Id即刻返回:sql
讓咱們再GET一下試試(注意:返回的ContactAddress是null,而事實上數據庫裏是有值的。這裏返回null的緣由是由於咱們沒有在Entity Framework中經過Include調用進行飢餓加載(Eager Loading),接下來會嘗試解決這個問題):數據庫
除了ContactAddress在GET請求中返回爲null以外,其它各類行爲,包括數據服務所支持的API接口、調用方式等,都與以前MongoDB的實現徹底相同。express
本文案例中的源代碼能夠在Apworks Examples開源項目中找到。本案例的源代碼在Apworks.Examples.CustomerService.EntityFramework目錄下。編程
本文帶領着你們一塊兒預覽了Apworks數據服務對Entity Framework Core的支持,使得Apworks數據服務不只可使用MongoDB等NoSQL存儲方案,也可使用關係型數據庫存儲方案,並且編程體驗也是幾乎相同的。這對於不一樣應用場景下微服務的實現是很是有幫助的。雖然在Entity Framework Core的實現中,目前有些瑕疵,但我會盡快解決這個問題。api