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

 撒药拿拉的唐小妄 发布于 2023-02-08 18:42

使用这个:

https://genericunitofworkandrepositories.codeplex.com/

和以下一组博客文章:

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 with Business Logic的任何示例都非常有用,特别是如果它直接在BeforeSaveEntity方法中发生在服务,存储库或其他内容中.

1 个回答
  • 这是许多问题集合在一起,每个问题都是一个很大的主题.我能做的最好的事情就是指向某个方向.

    我得到滚动之前,让我解释一下为什么你没有看到设置"的作用一样性质ModifiedBy,ModifiedTime,CreatedBy,等) ".在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控制器中实例化Breeze .该控制器(或多个控制器)将委托给负责业务逻辑和数据访问的外部类,可能是存储库或工作单元(UoW)类.

    使用Breeze .NET组件的存储库模式

    我们倾向于为模型(通常是POCO),数据访问(ORM)和Web(Web API加客户端资产)项目创建单独的项目.您将在DocCode示例和John Papa的Code Camper示例中看到这种分离,这是他的PluralsSight课程" 使用Angular和Breeze构建应用程序 "的伴侣.

    这些示例还演示了存储库模式的实现,该模式将多个存储库和UoW的职责混合在一个类中.这对于这些样品中的小型模型是有意义的.没有什么可以阻止您将存储库重构为单独的类.

    我们将我们的存储库类保存在与EF数据访问材料相同的项目中,因为我们认为在为这个小目的创建另一个项目时没有特别的价值.如果你决定这样做,重构成一个单独的项目并不困难.

    Breeze和Code Camper样本都专注于Breeze客户端开发.它们在服务器端逻辑上很薄.也就是说,您将BeforeSaveEntities在DocCode示例中的"NorthwindRepository.cs"和"NorthwindEntitySaveGuard.cs"文件的扩展点中找到有用的自定义业务逻辑线索.您将看到如何将保存限制为某些类型和某些记录这些类型的类型基于发出请求的用户.

    如果您尝试通过单个端点引导所有保存更改请求,则逻辑可能会非常大.你不必那样做.您可以拥有多个保存端点,每个端点专用于特定的业务操作,仅限于以高度特定的方式插入/更新/删除几种类型的实体.你可以随心所欲.请参阅" 保存实体"主题中的"命名保存" .

    按自己的方式行事吧

    现在有很多方法可以实现存储库和UoW模式.

    你可以按照你引用的帖子提出的方式行事.在这种情况下,您不需要Breeze .NET组件.将Web API查询方法(IQueryable或不是)连接到返回IQueryable(或只是对象)的存储库方法是非常简单的.Web API无需知道您是否EFContextProvider在幕后制作了Breeze 或完全不同的东西.

    处理Breeze客户端的SaveChanges请求有点棘手.也许你可以从派生ContextProviderEFContextProvider; 也许不吧.研究"ContextProvider.cs"文档和源代码,特别是SaveChanges方法,您将看到您需要做些什么来保持Breeze客户端满意和接口,但是您希望使用您的UoW处理更改集保存.

    假设您在客户端没有任何改变(这是一个假设,而不是给定......如果您愿意,可以更改保存协议),您SaveChanges只需要做两件事:

      从客户端解释"saveBundle".

      返回一些结构相似的东西 SaveResult

    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"并调度到您的业务逻辑.

    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,而不是这些类型.

    2023-02-08 18:44 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有