这是许多问题合而为一的问题,每个问题都是一个大主题。我能做的就是为你指明一些方向。
在开始之前,让我解释一下为什么您看不到设置的效果“属性如ModifiedBy
, ModifiedTime
, CreatedBy
, etc)". The EFContextProvider
不更新的每个属性修改实体而只是那些在EntityInfo.OriginalValuesMap
,属性名称和已更改属性的原始值的字典。如果您想保存仅在服务器上设置的属性,只需将其添加到原始值映射中即可:
var map = EntityInfo.OriginalValuesMap;
map["ModifiedBy"]=null; // the original value does not matter
map["ModifiedTime"]=null;
现在 Breeze 也知道要保存这些属性,并且它们的新值将返回给客户端。
让我们回到更大的图景。
Breeze 首先是一个客户端 JavaScript 库。您可以在服务器端做几乎任何您想做的事情,只要您的服务器使用 HTTP 和 JSON,就可以让 Breeze 满意。
无论您喜欢哪种技术,编写一个提供您所需的所有功能的服务器都不是一件容易的事。 Breeze 的作者提供了一些开箱即用的 .NET 组件,使您的工作更加轻松,特别是当您选择 Web API、EF 和 SQL Server 堆栈时。
我们的 .NET 演示通常将所有内容都放入一个 Web 应用程序中。这不是我们在实践中的做法。在现实生活中我们永远不会实例化微风EFContextProvider
在我们的 Web API 控制器中。该控制器(或多个控制器)将委托给负责业务逻辑和数据访问的外部类,可能是存储库或工作单元 (UoW) 类。
具有 Breeze .NET 组件的存储库模式
我们倾向于为模型(通常是 POCO)、数据访问 (ORM) 和 Web(Web API 加客户端资产)项目创建单独的项目。你会在文档代码示例 http://www.breezejs.com/samples/doccode以及 John Papa 的 Code Camper 样本,这是他的 Pluralsight 课程的配套“使用 Angular 和 Breeze 构建应用程序 http://pluralsight.com/training/Courses/TableOfContents/build-apps-angular-breeze".
这些示例还演示了存储库模式的实现,该模式将多个存储库和 UoW 的职责混合在一个类中。这对于这些样本中的小模型来说是有意义的。没有什么可以阻止您将存储库重构为单独的类。
我们将存储库类保留在与 EF 数据访问材料相同的项目中,因为我们认为为此小目的创建另一个项目没有特别的价值。如果您决心这样做,那么重构为一个单独的项目并不困难。
Breeze 和 Code Camper 示例都专注于 Breeze 客户端开发。它们的服务器端逻辑很薄弱。也就是说,您将在以下内容中找到应用自定义业务逻辑的宝贵线索:BeforeSaveEntities
DocCode 示例中的“NorthwindRepository.cs”和“NorthwindEntitySaveGuard.cs”文件中的扩展点。您将看到如何根据发出请求的用户将保存限制为某些类型以及这些类型的某些记录。
如果您尝试通过单个端点传输所有保存更改请求,则逻辑可能会令人难以承受。你不必这样做。您可以有多个保存端点,每个端点专用于特定的业务操作,该操作仅限于以高度特定的方式插入/更新/删除几种类型的实体。您可以随心所欲地细化。请参阅“命名保存”“拯救实体”主题 http://www.breezejs.com/documentation/saving-changes.
随心所欲
现在有无数种方法可以实现存储库和 UoW 模式。
您可以按照您引用的帖子所述的方式进行操作。在这种情况下,您不需要 Breeze .NET 组件。连接 Web API 查询方法非常简单(IQueryable
或不)返回的存储库方法IQueryable
(或只是对象)。 Web API 不必知道您是否拥有 BreezeEFContextProvider
在幕后或完全不同的事情。
处理 Breeze 客户的SaveChanges
请求有点棘手。也许你可以从中得出ContextProvider
or EFContextProvider
;也许不会。研究“ContextProvider.cs”文档 http://www.breezejs.com/documentation/contextprovider和源代码 https://github.com/IdeaBlade/Breeze/blob/master/Breeze.ContextProvider/ContextProvider.cs,尤其是SaveChanges
方法,您将看到需要做什么才能让 Breeze 客户端满意,并与您希望通过 UoW 处理更改集保存的方式进行交互。
假设您在客户端没有进行任何更改(这是假设,不是给定的......如果您愿意,您可以更改保存协议),您的SaveChanges
只需要做两件事:
- 解释来自客户端的“saveBundle”。
- 返回结构相似的东西
SaveResult
The saveBundle
是一个您可能不想自己解压的 JSON 包。幸运的是,您可以从中派生一个类ContextProvider
您只需使用它来转动saveBundle
进入“SaveMap”,一个字典EntityInfo
这些对象几乎是任何人在分析更改集以进行验证和保存时都希望使用的对象。
以下可能会解决问题:
using System;
using System.Collections.Generic;
using System.Data;
using Breeze.ContextProvider;
using Newtonsoft.Json.Linq;
public class SaveBundleToSaveMap : ContextProvider
{
// Never create a public instance
private SaveBundleToSaveMap(){}
/// <summary>
/// Convert a saveBundle into a SaveMap
/// </summary>
public static Dictionary<Type, List<EntityInfo>> Convert(JObject saveBundle)
{
var dynSaveBundle = (dynamic) saveBundle;
var entitiesArray = (JArray) dynSaveBundle.entities;
var provider = new SaveBundleToSaveMap();
var saveWorkState = new SaveWorkState(provider, entitiesArray);
return saveWorkState.SaveMap;
}
// override abstract members but DO NOT USE ANY OF THEM
}
然后由您决定如何使用“SaveMap”并分派到您的业务逻辑。
The SaveResult
是一个简单的结构:
public class SaveResult {
public List<Object> Entities; // each of the entity type you serialize to the client
public List<KeyMapping> KeyMappings;
public List<Object> Errors;
}
public class KeyMapping {
public String EntityTypeName;
public Object TempValue;
public Object RealValue;
}
按原样使用这些类或构建您自己的类。 Breeze 客户端关心的是 JSON,而不是这些类型。