如何将 Breeze 与通用工作单元和存储库一起使用?

2024-01-07

使用这个:

https://genericunitofworkandrepositories.codeplex.com/ https://genericunitofworkandrepositories.codeplex.com/

以及以下一组博客文章:

http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/ http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/

我们正在尝试使用这些存储库Breeze因为它可以很好地处理客户端 javascript 和 OData。

我想知道我们如何使用这些Breeze来处理覆盖BeforeSaveEntity正确。

我们有相当多的业务逻辑需要在保存期间发生(修改属性,例如ModifiedBy, ModifiedTime, CreatedBy等),但是当我们更改这些内容时,它们不会被微风更新,因此我们必须在保存后重新查询(我们尝试手动将更改映射回来,但这需要我们复制所有业务逻辑)。

我们的第二个选择是检查每个的类型entity然后为其请求正确的存储库,在内部处理保存,然后在客户端上执行新的 get 请求以获取更新的信息。虽然这很啰嗦,所以我们希望有更好的方法。在绕过微风保存而不返回错误或随后必须重新获取数据的情况下更新这些对象的正确方法是什么?

保存过程中使用业务逻辑的 Breeze 的任何示例都会非常有帮助,特别是如果它发生在服务、存储库或其他东西中,而不是直接在BeforeSaveEntity method.


这是许多问题合而为一的问题,每个问题都是一个大主题。我能做的就是为你指明一些方向。

在开始之前,让我解释一下为什么您看不到设置的效果“属性如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 客户端开发。它们的服务器端逻辑很薄弱。也就是说,您将在以下内容中找到应用自定义业务逻辑的宝贵线索:BeforeSaveEntitiesDocCode 示例中的“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只需要做两件事:

  1. 解释来自客户端的“saveBundle”。
  2. 返回结构相似的东西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,而不是这些类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 Breeze 与通用工作单元和存储库一起使用? 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐