どのようにAsp.Net Coreの中でABP Dapperを集積しますか?


実際のプロジェクトでは、ABPフレームを統合したEnttityFraamewarkCore以外にも、いくつかの特定のシーンではSQLクエリ文が避けられないが、一方では現在のEntity Frame orkCore 2.Xによって解決されていない問題があり、もう一方では、性能面を考慮して、本編の内容を理解する前に、まず、公式文書による説明を見てみましょう。
公式の紹介では、全体として次の手順に分けることができます。2 Depends On属性ラベルを追加します。3 Entity to Table Mapping。4 Usageは上の4つのステップによって、Asp.Net CoreプロジェクトでABP Dapperを正常に使用することができます。具体的な過程について説明します。
一取り付けパッケージ依存
これはあまり説明しないで、Nugetパッケージマネージャまたはプログラムパッケージ管理コンソールによってAbp.Dapperの引用を追加して、私達の実際のプロジェクトの中で全種類のライブラリの構造は下図のようになっています。

二にDepends On属性ラベルを追加します。
後に私達は今のクラスのプロジェクトの中で唯一のSalesDataModuleでいくつかの初期化とDepends Onラベルを追加する操作をしなければなりません。

[DependsOn(typeof(AbpZeroCoreEntityFrameworkCoreModule))]
    [DependsOn(typeof(AbpDapperModule))]
    public class SalesDataModule : AbpModule {
        public override void Initialize() {         
            IocManager.RegisterAssemblyByConvention(typeof(SalesDataModule).GetAssembly());
            DapperExtensions.DapperExtensions.SetMappingAssemblies(new List<Assembly> { typeof(SalesDataModule).GetAssembly() });
        }
    }
ここではなぜ依存関係を追加するのかを知るべきです。これは私達の現在のSalesData ModuleがAbpDapperModuleとAbpZerCoreEntityFrame eweet Coremoduleに依存します。このような依存関係を確立したら、ABPフレームワークで現在のModuleが依存している他のModuleをList<AbpModule>の前に置いて、このようにして、階層的な依存関係をトポロジに並べ替えることによって、依存されているAbpModuleが必ず初期化操作を行うことを保証することができ、これにより、参照関係のエラーを回避でき、コード論理のエラーを引き起こし、具体的には、AがBに依存する場合、BがCに依存する場合、この3つのモジュールの間の並べ替えはC B Aとなり、Moduleシステム全体が初期化されるとき、先にModule CのPreIntialize()、Initialize()、PostInitialize()の方法を実行します。ABPのソースコードを見てみます。

public virtual void StartModules()
      {
          var sortedModules = _modules.GetSortedModuleListByDependency();
          sortedModules.ForEach(module => module.Instance.PreInitialize());
          sortedModules.ForEach(module => module.Instance.Initialize());
          sortedModules.ForEach(module => module.Instance.PostInitialize());
      }
この中のsortedModulesはこの依存関係を通してトポロジカルに並べ替えられ、この行の各モジュールにおけるこれらの方法によっていくつかの初期化動作を行う。
三Entity to Table Mapping
これは公式の解釈によると、Entityとデータベースエンティティとの関係を確立しています。これはDomain層エンティティに「Table」ラベル(個人的な理解)を追加しています。この中には他の特性を追加します。例えばIgnoreがナビゲーションの属性を落とすなどです。

public sealed class VehicleOrderPlanMapper : ClassMapper<VehicleOrderPlan> {
    public VehicleOrderPlanMapper() {
        Table("VehicleOrderPlan");
        Map(x => x.Branch).Ignore();
        AutoMap();
    }
}
アプリケーション
この部分は具体的なプロジェクトと結び付けて、細かいところについて話します。まず具体的なコードを見てみます。

public class VehicleOrderPlanDapperRepository : DcsDapperRepositoryBase<VehicleOrderPlan>, IVehicleOrderPlanDapperRepository {
        public VehicleOrderPlanDapperRepository(IActiveTransactionProvider activeTransactionProvider) : base(activeTransactionProvider) {
        }
 
        public IEnumerable<WeeklyOrderPlanSummary> GetWeeklyOrderPlanSummary(int? yearOfPlan, int? weekOfPlan, string provinceName,
            [CanBeNull]VehicleOrderPlanType[] planType, string marketName, PageRequest page) {
            var sqlParam = new StringBuilder()
                .AppendIf(yearOfPlan.HasValue, $" AND p.YearOfPlan = :{nameof(yearOfPlan)}")
                .AppendIf(weekOfPlan.HasValue, $" AND p.WeekOfPlan = :{nameof(weekOfPlan)}")
                .AppendIf(!provinceName.IsNullOrWhiteSpace(), $@" AND EXISTS ( SELECT 1
    FROM Company C WHERE c.Id = p.DealerId AND c.Status <> {(int)MasterDataStatus.  }
        AND c.ProvinceName like '%' || :{nameof(provinceName)} || '%')");
 
            var planTypes = new[] {
                VehicleOrderPlanType.    ,
                VehicleOrderPlanType.     ,
                VehicleOrderPlanType.    
            };
            if (planType != null && planType.Length > 0)
                planTypes = planTypes.Intersect(planType).ToArray();
 
            var departmentParam = string.Empty;
            if (!marketName.IsNullOrWhiteSpace())
                departmentParam = $" AND (m.Name LIKE '%' || :{nameof(marketName)} || '%')";
 
            var sql = $@"
SELECT p.YearOfPlan, p.WeekOfPlan, TRUNC(p.CreateTime) AS CreateTime, TRUNC(p.StartTime) AS StartTime, TRUNC(p.EndTime) AS EndTime,
       pd.ProductCode, pd.ProductName, pd.ProductType, pd.ProductCategoryCode AS VehicleModelCode, pd.ProductCategoryName AS VehicleModelName,
       Sum(pd.PlannedQuantity) AS PlannedQuantity, Sum(pd.FirstPlannedQuantity) AS FirstPlannedQuantity,
       Sum(pd.QuantityOfAssessment) AS QuantityOfAssessment, Sum(pd.ConfirmedQuantity) AS ConfirmedQuantity
FROM VehicleOrderPlan p
CROSS JOIN VehicleOrderPlanDetail pd
WHERE (p.Status <> {(int)VehicleOrderPlanStatus.  } AND p.Type in {planTypes.ToSqlInParam()} {sqlParam} AND EXISTS (
    SELECT 1
    FROM DealerMarketDptRelation dm
    WHERE (((dm.BranchId = p.BranchId) AND (dm.DealerId = p.DealerId)) AND (dm.Status = {(int)BaseDataStatus.  })) AND EXISTS (
        SELECT 1
        FROM MarketingDepartment m
        WHERE ((m.BranchCode = {SunlightConsts.DEFAULT_BRANCH_QRSALESLTD}) AND (m.Status = {(int)BaseDataStatus.  })) {departmentParam}
            AND (m.Id = dm.MarketId)))) AND (p.Id = pd.VehicleOrderPlanId)
GROUP BY p.YearOfPlan, p.WeekOfPlan, TRUNC(p.CreateTime), TRUNC(p.StartTime), TRUNC(p.EndTime), pd.ProductCode,
         pd.ProductName, pd.ProductType, pd.ProductCategoryCode, pd.ProductCategoryName";
 
            return QueryPaged<WeeklyOrderPlanSummary>(sql, page, new {
                yearOfPlan,
                weekOfPlan,
                provinceName,
                marketName
            });
        }
    }
このコードは主に具体的に入ってきたパラメーター計画年、計画週間、省…などのパラメーターを通じてデータベースの中で関連記録を調べます。ここでまず基質Dcs DapperRepositoryBase<VehicleOrderPlan>の中で何をしましたか?

public class DcsDapperRepositoryBase<TEntity> : DapperEfRepositoryBase<DcsDbContext, TEntity>
        where TEntity : class, IEntity<int> {
        public DcsDapperRepositoryBase(IActiveTransactionProvider activeTransactionProvider) : base(activeTransactionProvider) {
        }
 
        /// <summary>
        ///           
        /// </summary>
        /// <typeparam name="TValueObject"></typeparam>
        /// <param name="sql"></param>
        /// <param name="pageRequest"></param>
        /// <param name="parameters">       </param>
        /// <returns></returns>
        protected IEnumerable<TValueObject> QueryPaged<TValueObject>(string sql, PageRequest pageRequest, object parameters = null)
            where TValueObject : ValueObjectBase {
            var orderCondition = (string.IsNullOrWhiteSpace(pageRequest.Ordering) ? string.Empty : "ORDER BY " + pageRequest.Ordering);
            orderCondition.SqlInjectionInspect();
            var pagedSql = $@"WITH ""_data"" AS ({sql}),
     ""_count"" AS (SELECT COUNT(0) AS OverallCount FROM ""_data"")
SELECT *
FROM (SELECT A.*, ROWNUM AS ""RowNum""
      FROM (SELECT * FROM ""_data""
            {orderCondition}) A
      WHERE ROWNUM <= {pageRequest.PageSize * (pageRequest.PageIndex + 1)}) B,
     ""_count""
WHERE ""RowNum"" > {pageRequest.PageSize * pageRequest.PageIndex}";
            return Query<TValueObject>(pagedSql, parameters);
        }
    }
この基質ではABPの基質DapperEfRepositoryBase、この汎型ベースの最初のパラメータは私達のプロジェクトの具体的なDbContextであり、第二のパラメータは私達が具体的に定義したエンティティであり、このエンティティは主キーがIntの自己成長タイプである。この中には照会のデータが非常に多いので、ここで実際に戻ってきたのは改ページの第一ページの結果集です。ここで重要な知識があります。sql注入を防止するために、ここでsqlのパラメータはすべてパラメータの匿名の対象を採用しています。直接スプライスを行うのではなく、SQL注入を防止する時に最も一般的な方法です。この具体的な例を通して、ABP Dapperでは匿名パラメータオブジェクトを使ってSQL注入を防ぐ方法を知るべきです。また、このSQLを通じて、Oracleデータベースで照会した結果をどのようにページ分けして処理するかも分かります。
これらを処理した後、現在のVehicleOrderPlanRepositoryの継承インターフェースはどこで定義されていますか?具体的な分野層はどうやって呼び出しますか?

public interface IVehicleOrderPlanDapperRepository : IDapperRepository<VehicleOrderPlan> {
       IEnumerable<WeeklyOrderPlanSummary> GetWeeklyOrderPlanSummary(int? yearOfPlan, int? weekOfPlan, string provinceName,
           [CanBeNull] VehicleOrderPlanType[] planType, string marketName, PageRequest page);
   }
このインターフェースはとても簡単ですが、このインターフェースは一体どこで定義されますか?私達はDDDの思想に基づいて、まず思い付いたのは領域の階で定義を行うので、さもなくば領域の階のその他の業務はどこでこの方法を呼び出すべきですか?これはどこで答えが見つけられますか?

この図に詳しいのかどうか、これはABP N層構造を紹介するための模式図であり、赤枠の表記は具体的な構造の中のインターフェース定義と実現であり、この両者の定義と実現はそれぞれ異なる層の中にあり、一つはDomain Layerに属し、具体的な実現はInfrastucture Layerにあり、一つはインターフェースを定義する。もう一つの階は具体的な実現を定義しています。これがあったら、ABP全体の構造についてもっと深く理解できますか?
以上はどのようにAsp.Net CoreにABP Dapperの詳しい内容を統合しますか?Asp.Net CoreについてABP Dapperの資料を統合します。他の関連記事に注目してください。