.NetCoreのDapper

I.はじめに

  Dapperとは何かについては、ここでは詳しく説明しません。この記事では、.Net CoreでのDapperの使用について簡単に説明します。提示されたコードは主に例に基づいており、単なるガイドです。開発者はそれに応じて拡張および調整できます。自分のニーズに合わせて;抜けがある場合は、お気軽に修正してください。

2.ダッパー環境構築

現在、.Net Core WebAPIまたはMVCプロジェクトを例にとると、フレームワークのバージョンは.NET 5.0であり、関連するNuGetパッケージの参照は次のとおりです。

インストール-パッケージダッパー

インストール-パッケージDapper.Contrib

インストール-パッケージDapper.SqlBuilder

Install-Package System.Data.SqlClient

その中で、Dapper.ContribとDapper.SqlBuilderはDapperの拡張機能です。もちろん、Dapperの拡張機能には、Dapper.Rainbowなどの他のパッケージが含まれており、それぞれのニーズに応じて参照できます。関連する参照については、次のように説明します。

  • Dapper:言うまでもありません。
  • Dapper.Contrib:オブジェクトを使用して、データテーブルを追加、削除、変更、およびクエリできるため、SQLステートメントを作成する必要がありません。
  • Dapper.SqlBuilder:Join、SELECT、Where、OrderByなどのSQLステートメントを動的に作成すると便利です。
  • System.Data.SqlClient:サンプルデータベースはMySqlなどのSQL Serverであるため、MySql.Dataを参照してください。


Dapper.Contribエンティティ構成オプションの場合、Productクラスを例にとると、簡単な説明は次のとおりです。

[Table("Product")]
public class Product
{
    [Key]  
    public int Id { get; set; }
    public string Name{ get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public DateTime CreateTime { get; set; }
}

エンティティ構成アイテムには、次の主なアイテムがあります。

  • テーブル:データベーステーブル名を指定します。これは無視できます。
  • キー:自動インクリメントの主キーとして指定されます。
  • ExplicitKey:guidなどの自動拡張されない主キーを指定します。
  • 計算済み:計算済みの列属性。挿入および更新操作では無視されます。
  • 書き込み:書き込み可能かどうか、[Write(false)]などのtrue / false、falseの場合、挿入および更新操作はこの列を無視します。たとえば、拡張可能な部分クラスは、データ表;

データテーブルオブジェクトエンティティの場合、T4テンプレートと組み合わせて生成できます。

3.ダッパーパッケージ

次のようにパッケージを調整するための変更を行います。

DapperDBContextクラスを定義します

 コードを表示

 コードを表示

上記のコードは、データベースにアクセスするDapperの基本的な操作をカバーしており、同期と非同期に分けられます。これらのほとんどは繰り返されず、次のページング部分に焦点が当てられます。

非同期ページング構造(PageAsync)

ページングの便宜のために、照会するSqlステートメント(SELECT * FROM Table、Order BYを含める必要がありますなど)、ページインデックス、およびページサイズを渡すだけで済みます。

構築方法については、小さなORMツールであるPetaPocoを参照し、次のように関連するコードを抽出してください。興味のある学生は、自分で変換することもできます。

public class Page<T>
    {
        /// <summary>
        /// The current page number contained in this page of result set 
        /// </summary>
        public long CurrentPage { get; set; }

        /// <summary>
        /// The total number of pages in the full result set
        /// </summary>
        public long TotalPages { get; set; }

        /// <summary>
        /// The total number of records in the full result set
        /// </summary>
        public long TotalItems { get; set; }

        /// <summary>
        /// The number of items per page
        /// </summary>
        public long ItemsPerPage { get; set; }

        /// <summary>
        /// The actual records on this page
        /// </summary>
        public IEnumerable<T> Items { get; set; }
        //public List<T> Items { get; set; }
    }
    public class DapperPage
    {
        public static void BuildPageQueries(long skip, long take, string sql, out string sqlCount, out string sqlPage)
        {
            // Split the SQL
            if (!PagingHelper.SplitSQL(sql, out PagingHelper.SQLParts parts))
                throw new Exception("Unable to parse SQL statement for paged query");

            sqlPage = BuildPageSql.BuildPageQuery(skip, take, parts);
            sqlCount = parts.sqlCount;
        }
    }

    static class BuildPageSql
    {
        public static string BuildPageQuery(long skip, long take, PagingHelper.SQLParts parts)
        {
            parts.sqlSelectRemoved = PagingHelper.rxOrderBy.Replace(parts.sqlSelectRemoved, "", 1);
            if (PagingHelper.rxDistinct.IsMatch(parts.sqlSelectRemoved))
            {
                parts.sqlSelectRemoved = "peta_inner.* FROM (SELECT " + parts.sqlSelectRemoved + ") peta_inner";
            }
            var sqlPage = string.Format("SELECT * FROM (SELECT ROW_NUMBER() OVER ({0}) peta_rn, {1}) peta_paged WHERE peta_rn>{2} AND peta_rn<={3}",
                                    parts.sqlOrderBy ?? "ORDER BY (SELECT NULL)", parts.sqlSelectRemoved, skip, skip + take);
            //args = args.Concat(new object[] { skip, skip + take }).ToArray();

            return sqlPage;
        }

        //SqlServer 2012及以上
        public static string BuildPageQuery2(long skip, long take, PagingHelper.SQLParts parts)
        {
            parts.sqlSelectRemoved = PagingHelper.rxOrderBy.Replace(parts.sqlSelectRemoved, "", 1);
            if (PagingHelper.rxDistinct.IsMatch(parts.sqlSelectRemoved))
            {
                parts.sqlSelectRemoved = "peta_inner.* FROM (SELECT " + parts.sqlSelectRemoved + ") peta_inner";
            }    

            var sqlOrderBy = parts.sqlOrderBy ?? "ORDER BY (SELECT NULL)";
            var sqlPage = $"SELECT {parts.sqlSelectRemoved} {sqlOrderBy} OFFSET {skip} ROWS FETCH NEXT {take} ROWS ONLY";
            return sqlPage;
        }
    }

    static class PagingHelper
    {
        public struct SQLParts
        {
            public string sql;
            public string sqlCount;
            public string sqlSelectRemoved;
            public string sqlOrderBy;
        }

        public static bool SplitSQL(string sql, out SQLParts parts)
        {
            parts.sql = sql;
            parts.sqlSelectRemoved = null;
            parts.sqlCount = null;
            parts.sqlOrderBy = null;

            // Extract the columns from "SELECT <whatever> FROM"
            var m = rxColumns.Match(sql);
            if (!m.Success)
                return false;

            // Save column list and replace with COUNT(*)
            Group g = m.Groups[1];
            parts.sqlSelectRemoved = sql.Substring(g.Index);

            if (rxDistinct.IsMatch(parts.sqlSelectRemoved))
                parts.sqlCount = sql.Substring(0, g.Index) + "COUNT(" + m.Groups[1].ToString().Trim() + ") " + sql.Substring(g.Index + g.Length);
            else
                parts.sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length);


            // Look for the last "ORDER BY <whatever>" clause not part of a ROW_NUMBER expression
            m = rxOrderBy.Match(parts.sqlCount);
            if (!m.Success)
            {
                parts.sqlOrderBy = null;
            }
            else
            {
                g = m.Groups[0];
                parts.sqlOrderBy = g.ToString();
                parts.sqlCount = parts.sqlCount.Substring(0, g.Index) + parts.sqlCount.Substring(g.Index + g.Length);
            }

            return true;
        }

        public static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
        public static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?!.*?(?:\)|\s+)AS\s)(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
        public static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
    }

ページングステートメントを作成する場合の例は、BuildPageQueryとBuildPageQuery2です。前者はROW_NUMBER SqlServer2005および2008の場合)を介してページングし、後者はOFFSETおよびFETCH(SqlServer2012以降の場合)を介してページングします。データベース。必要に応じてカプセル化できます。 

Whereクエリのさらなるカプセル化については、興味のある人はDapperlamadaクエリを使用して拡張することもできます。

作業単位とトランザクションの定義

 コードを表示

データウェアハウスを定義する

 コードを表示

通常、T4テンプレートを使用して生成された、独自のニーズに応じて調整または拡張します

データベースリンケージ

Ioptionsモードを介して構成ファイルappsettingsの接続文字列を読み取ります
 

public class MyDBContext : DapperDBContext
    {
        public MyDBContext(IOptions<DapperDBContextOptions> optionsAccessor) : base(optionsAccessor)
        {
        }

        protected override IDbConnection CreateConnection(string connectionString)
        {
            IDbConnection conn = new SqlConnection(connectionString);
            return conn;
        }
    }

第四に、Dapperの使用

Startup.csは、データベース接続文字列を挿入して読み取ります

{
  "SQLConnString": "Data Source=(local);Initial Catalog=database;Persist Security Info=True;User ID=sa;Password=123456;MultipleActiveResultSets=True;",  
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
services.AddDapperDBContext<MyDBContext>(options =>
            {
                options.Configuration = Configuration["SQLConnString"];
            });

単純な例のWebAPIまたはNetCoreMVCでの呼び出し例:

 コードを表示

 コードを表示

おすすめ

転載: blog.csdn.net/weixin_55305220/article/details/122403176