Rumah pembangunan bahagian belakang Tutorial C#.Net DapperExtensions和反射实现通用搜索(ASP.NET)

DapperExtensions和反射实现通用搜索(ASP.NET)

May 03, 2017 pm 01:28 PM

这篇文章主要介绍了Asp.net中使用DapperExtensions和反射来实现一个通用搜索功能,非常不错,具有参考解决价值,需要的朋友可以参考下

前言

  搜索功能是一个很常用的功能,当然这个搜索不是指全文检索,是指网站的后台管理系统或ERP系统列表的搜索功能。常见做法一般就是在搜索栏上加上几个常用字段来搜索。代码可能一般这样实现

StringBuilder sqlStr = new StringBuilder();
if (!string.IsNullOrEmpty(RealName))
{
  sqlStr.Append(" and RealName = @RealName");
}
if (Age != -1)
{
  sqlStr.Append(" and Age = @Age");
}
if (!string.IsNullOrEmpty(StartTime))
{
  sqlStr.Append(" and CreateTime >= @StartTime");
}
if (!string.IsNullOrEmpty(EndTime))
{
  sqlStr.Append(" and CreateTime <= @EndTime");
}
MySqlParameter[] paras = new MySqlParameter[]{
      new MySqlParameter("@Age", Age),
      new MySqlParameter("@RealName", RealName),
      new MySqlParameter("@StartTime", StartTime),
      new MySqlParameter("@EndTime", EndTime)
    };
Salin selepas log masuk

这段代码如果遇到下面几个需求,又该如何处理?

  1. 再加一个查询字段

  2. RealName需要改成模糊查询

  3. Age需要支持范围查询

可能大多数程序猿想法,这是新的需求,那么就直接改代码,简单粗暴。然后在前台加个age范围文本框,后台再加个if判断,realname的=号就直接改成like,就这样轻松搞定了。但需求总是不断变化,如果一张表有50个字段,同时需要支持其中40个字段查询。我想大都数人第一反应:卧槽,神经病!难道就没有一个通用的办法来解决这种搜索的问题?我想说当然有,本文接下来就用DapperExtensions和反射的来解决这个问题,最终于实现的效果如下图:

DapperExtensions介绍

  DapperExtensions是基于Dapper的一个扩展,主要在Dapper基础上实现了CRUD的操作。它还提供了一个谓词系统,可以实现更多复杂的高级查询功能。还可以通过ClassMapper来定义实体类和表的映射。

通用搜索功能实现

1.首先创建一个account表,然后增加一个Account类

public class Account
  {
    public Account()
    {
      Age = -1;
    }
    /// <summary>
    /// 账户ID
    /// </summary>
    [Mark("账户ID")]
    public int AccountId { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    [Mark("姓名")]
    public string RealName { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    [Mark("年龄")]
    public int Age { get; set; }
    /// <summary>
    /// 创建时间
    /// </summary>
    [Mark("创建时间")]
    public DateTime CreateTime { get; set; }
  }
Salin selepas log masuk

2.为了获取字段对应的中文名称,我们增加一个MarkAttribute类。因为有强大的反射功能,我们可以通过反射动态获取每张表实体类的属性和中文名称。

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
  public class MarkAttribute : Attribute
  {
    public MarkAttribute(string FiledName, string Description = "")
    {
      this.FiledName = FiledName;
      this.Description = Description;
    }
    private string _FiledName;
    public string FiledName
    {
      get { return _FiledName; }
      set { _FiledName = value; }
    }
    private string _Description;
    public string Description
    {
      get { return _Description; }
      set { _Description = value; }
    }
  }
Salin selepas log masuk

3.通用搜索思路主要是把搜索功能抽象出一个对象,本质上也就列名、操作符、值组成的一个对象集合,这样就可以实现多个搜索条件的组合。我们增加一个Predicate类

public class Predicate
  {
    /// <summary>
    /// 列名
    /// </summary>
    public string ColumnItem { get; set; }
    /// <summary>
    /// 操作符
    /// </summary>
    public string OperatorItem { get; set; }
    /// <summary>
    /// 值
    /// </summary>
    public object Value { get; set; }
  }
Salin selepas log masuk

4.然后通过反射Account类的属性加载到前台列名的DropDownList,再增加一个操作符的DropDownList

var columnItems = new List<SelectListItem>();
      //通过反射来获取类的属性
      Type t = Assembly.Load("SearchDemo").GetType("SearchDemo.Models.Account");
      foreach (PropertyInfo item in t.GetProperties())
      {
        string filedName = (item.GetCustomAttributes(typeof(MarkAttribute), false)[0] as MarkAttribute).FiledName;
        columnItems.Add(new SelectListItem() { Text = filedName, Value = item.Name });
      }
      ViewBag.columnItems = columnItems;
      var operatorItems = new List<SelectListItem>()
      {
        new SelectListItem() {Text = "等于", Value = "Eq"},
        new SelectListItem() {Text = "大于", Value = "Gt"},
        new SelectListItem() {Text = "大于或等于", Value = "Ge"},
        new SelectListItem() {Text = "小于", Value = "Lt"},
        new SelectListItem() {Text = "小于或等于", Value = "Le"},
        new SelectListItem() {Text = "模糊", Value = "Like"}
      };
      ViewBag.operatorItems = operatorItems;
Salin selepas log masuk

5.前台界面实现代码

<!DOCTYPE html>
<html>
<head>
  <title>DapperExtensions通用搜索</title>
  <script src="../../scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
  <script type="text/javascript">
    Date.prototype.format = function (format) {
      var o = {
        "M+": this.getMonth() + 1, //month  
        "d+": this.getDate(), //day  
        "h+": this.getHours(), //hour  
        "m+": this.getMinutes(), //minute  
        "s+": this.getSeconds(), //second  
        "q+": Math.floor((this.getMonth() + 3) / 3), //quarter  
        "S": this.getMilliseconds() //millisecond  
      }
      if (/(y+)/.test(format)) {
        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
      }
      for (var k in o) {
        if (new RegExp("(" + k + ")").test(format)) {
          format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
        }
      }
      return format;
    } 
  </script>
  <style type="text/css">
    ul
    {
      list-style: none;
      padding: 0px;
      margin: 0px;
      width: 590px;
      height: 20px;
      line-height: 20px;
      border: 1px solid #99CC00;
      border-top: 0px;
      font-size: 12px;
    }
    ul li
    {
      display: block;
      width: 25%;
      float: left;
      text-indent: 2em;
    }
    .th
    {
      background: #F1FADE;
      font-weight: bold;
      border-top: 1px solid #99CC00;
    }
  </style>
  <script type="text/javascript">
    var predicates = [];
    var index = 0;
    $(document).ready(function () {
      $("#btnAdd").click(function () {
        var columnItem = $("#columnItems option:selected");
        var operatorItem = $("#operatorItems option:selected");
        var value = $("#value").val();
        if(value == ""){
          alert("请输入值");
          return;
        }
        var predicate = { index: index, columnItem: columnItem.val(), operatorItem: operatorItem.val(), value: value };
        predicates.push(predicate);
        var html = "<ul><li>" + columnItem.text() + "</li><li>" + operatorItem.text() + "</li><li>" + value + "</li><li><a href=&#39;javascript:;&#39; onclick=&#39;del(this," + index + ")&#39;>删除</a></li></ul>"
        $("#predicates ul:last").after(html);
        index++;
      })
      $("#btnSearch").click(function () {
        $.ajax({
          type: "POST",
          url: "home/search",
          data: JSON.stringify(predicates),
          contentType: "application/json",
          success: function (data) {
            if (data.Error != null) {
              alert(data.Error);
              return;
            }
            $("#list .th").nextAll().remove();
            var html = "";
            $.each(data, function (index, item) {
              html += "<ul><li>" + item.AccountId + "</li>";
              html += "<li>" + item.RealName + "</li>";
              html += "<li>" + item.Age + "</li>";
              //转换日期
              var dateMilliseconds = parseInt(item.CreateTime.replace(/\D/igm, ""));
              var date = new Date(dateMilliseconds);
              html += "<li>" + date.format("yyyy-MM-dd hh:mm:ss") + "</li></ul>";
            });
            $("#list .th").after(html);
          }
        });
      })
    })
    function del(obj,index) {
      obj.parentNode.parentNode.remove();
      for (var i = 0; i < predicates.length; i++) {
        if (predicates[i].index == index) {
          predicates.splice(i, 1);
        }
      }
    }
  </script>
</head>
<body>
  <p>
    列名:@Html.DropDownList("columnItems")  操作符:@Html.DropDownList("operatorItems")  值:@Html.TextBox("value")  
    <input id="btnAdd" type="button" value="增加" />  <input id="btnSearch" type="button" value="搜索" />
  </p>
  <br />
  <p id="predicates">
    <ul class="th">
      <li>列名</li>
      <li>操作符</li>
      <li>值</li>
      <li>操作</li>
    </ul>
  </p>
  <br />
  <p id="list">
    <ul class="th">
      <li>账户ID</li>
      <li>姓名</li>
      <li>年龄</li>
      <li>创建时间</li>
    </ul>  
  </p>
</body>
</html>
Salin selepas log masuk

6.最后通过DapperExtensions的谓词和反射实现搜索方法

 [HttpPost]
    public JsonResult Search(List<Predicate> predicates)
    {
      if (predicates == null)
      {
        return Json(new { Error = "请增加搜索条件" });
      }
      using (var connection = SqlHelper.GetConnection())
      {
        var pga = new PredicateGroup { Operator = GroupOperator.And, Predicates = new List<IPredicate>() };
        foreach (var p in predicates)
        {
          var predicate = Predicates.Field<Account>(GetExpression(p), (Operator)Enum.Parse(typeof(Operator), p.OperatorItem), p.Value);
          pga.Predicates.Add(predicate);
        }
        var list = connection.GetList<Account>(pga);
        return Json(list);
      }
    }
    private static Expression<Func<Account, object>> GetExpression(Predicate p)
    {
      ParameterExpression parameter = Expression.Parameter(typeof(Account), "p");
      return Expression.Lambda<Func<Account, object>>(Expression.Convert(Expression.Property(parameter, p.ColumnItem), typeof(object)), parameter);
    }
Salin selepas log masuk

  最终,通过简单的几行代码,在基于DapperExtensions的功能基础上,我们最终实现了一个可以支持多个字段、多个条件、多个操作符的通用查询功能。本文也只是抛砖引玉,只是提供一种思路,还有更多细节没有考虑。比如多个条件的组合可以再增加一个逻辑符来连接、多个条件组合嵌套查询、多表查询等等。

Atas ialah kandungan terperinci DapperExtensions和反射实现通用搜索(ASP.NET). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Artikel Panas

R.E.P.O. Kristal tenaga dijelaskan dan apa yang mereka lakukan (kristal kuning)
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Tetapan grafik terbaik
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Cara Memperbaiki Audio Jika anda tidak dapat mendengar sesiapa
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Cara Membuka Segala -galanya Di Myrise
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Pelaksanaan mekanisme refleksi antara muka dan kelas abstrak di Jawa Pelaksanaan mekanisme refleksi antara muka dan kelas abstrak di Jawa May 02, 2024 pm 05:18 PM

Mekanisme pantulan membenarkan atur cara untuk mendapatkan dan mengubah suai maklumat kelas semasa runtime Ia boleh digunakan untuk melaksanakan refleksi antara muka dan kelas abstrak: Refleksi antara muka: mendapatkan objek pantulan antara muka melalui Class.forName() dan mengakses metadatanya (nama, kaedah dan. padang). Refleksi kelas abstrak: Sama seperti antara muka, anda boleh mendapatkan objek pantulan kelas abstrak dan mengakses metadata dan kaedah bukan abstraknya. Kes praktikal: Mekanisme pantulan boleh digunakan untuk melaksanakan proksi dinamik dan memintas panggilan ke kaedah antara muka pada masa jalan dengan mencipta kelas proksi secara dinamik.

Cara menggunakan refleksi untuk mengakses medan dan kaedah persendirian dalam golang Cara menggunakan refleksi untuk mengakses medan dan kaedah persendirian dalam golang May 03, 2024 pm 12:15 PM

Anda boleh menggunakan refleksi untuk mengakses medan dan kaedah peribadi dalam bahasa Go: Untuk mengakses medan peribadi: dapatkan nilai pantulan nilai melalui reflect.ValueOf(), kemudian gunakan FieldByName() untuk mendapatkan nilai pantulan medan dan panggil Kaedah String() untuk mencetak nilai medan . Panggil kaedah persendirian: dapatkan juga nilai pantulan nilai melalui reflect.ValueOf(), kemudian gunakan MethodByName() untuk mendapatkan nilai pantulan kaedah, dan akhirnya panggil kaedah Call() untuk melaksanakan kaedah. Kes praktikal: Ubah suai nilai medan persendirian dan panggil kaedah persendirian melalui refleksi untuk mencapai kawalan objek dan liputan ujian unit.

Kaedah untuk menyelesaikan pengecualian refleksi Java (ReflectiveOperationException) Kaedah untuk menyelesaikan pengecualian refleksi Java (ReflectiveOperationException) Aug 26, 2023 am 09:55 AM

Kaedah untuk menyelesaikan pengecualian pantulan Java (ReflectiveOperationException) Dalam pembangunan Java, pantulan (Refleksi) ialah mekanisme berkuasa yang membolehkan atur cara memperoleh dan mengendalikan kelas secara dinamik, objek, kaedah, sifat, dsb. pada masa jalan. Melalui refleksi, kita boleh melaksanakan beberapa fungsi fleksibel, seperti mencipta objek secara dinamik, memanggil kaedah persendirian, mendapatkan anotasi kelas, dsb. Walau bagaimanapun, menggunakan refleksi juga membawa beberapa potensi risiko dan masalah, salah satunya adalah anomali refleksi (

Cara menggunakan pantulan untuk mengubah suai nilai pembolehubah secara dinamik dalam golang Cara menggunakan pantulan untuk mengubah suai nilai pembolehubah secara dinamik dalam golang May 02, 2024 am 11:09 AM

Refleksi bahasa Go membolehkan anda memanipulasi nilai pembolehubah pada masa jalan, termasuk mengubah suai nilai Boolean, integer, nombor titik terapung dan rentetan. Dengan mendapatkan Nilai pembolehubah, anda boleh memanggil kaedah SetBool, SetInt, SetFloat dan SetString untuk mengubah suainya. Sebagai contoh, anda boleh menghuraikan rentetan JSON ke dalam struktur dan kemudian menggunakan refleksi untuk mengubah suai nilai medan struktur. Perlu diingatkan bahawa operasi pantulan adalah perlahan dan medan yang tidak boleh diubah suai tidak boleh diubah suai Apabila mengubah nilai medan struktur, medan yang berkaitan mungkin tidak dikemas kini secara automatik.

Pengenalan kepada refleksi Golang dan analisis senario aplikasi Pengenalan kepada refleksi Golang dan analisis senario aplikasi Apr 03, 2024 pm 01:45 PM

Ciri pantulan dalam bahasa Go membolehkan program untuk memeriksa dan mengubah suai struktur sesuatu jenis pada masa jalan. Dengan menggunakan Type, Value dan reflect.Kind, kita boleh mendapatkan maklumat jenis, nilai medan dan kaedah objek, dan kita juga boleh mencipta dan mengubah suai objek. Kaedah operasi khusus termasuk: jenis menyemak (TypeOf()), mendapatkan nilai medan (ValueOf(), FieldByName()), mengubah suai nilai medan (Set()), dan mencipta objek (New()).

Pertimbangan keselamatan dan penyelesaian terbaik untuk refleksi golang Pertimbangan keselamatan dan penyelesaian terbaik untuk refleksi golang May 04, 2024 pm 04:48 PM

Reflection menyediakan keupayaan menyemak jenis dan pengubahsuaian dalam Go, tetapi ia mempunyai risiko keselamatan, termasuk pelaksanaan kod sewenang-wenangnya, pemalsuan jenis dan kebocoran data. Amalan terbaik termasuk mengehadkan kebenaran reflektif, operasi, menggunakan senarai putih atau senarai hitam, mengesahkan input dan menggunakan alat keselamatan. Dalam amalan, refleksi boleh digunakan dengan selamat untuk memeriksa maklumat jenis.

Cara menggunakan refleksi untuk mencipta jenis baharu dalam golang Cara menggunakan refleksi untuk mencipta jenis baharu dalam golang May 01, 2024 am 09:21 AM

Menggunakan refleksi, Go membolehkan penciptaan jenis baharu 1. Gunakan reflect.TypeOf() untuk mendapatkan nilai reflect.Type jenis sedia ada 2. Gunakan reflect.New() untuk mencipta nilai penunjuk jenis baharu; . Melalui *Ptr.Elem( ) untuk mengakses nilai sebenar; 4. Refleksi juga boleh mencipta jenis baharu secara dinamik berdasarkan rentetan, yang digunakan untuk membina atur cara yang fleksibel dan dinamik.

Menggunakan mekanisme refleksi Java untuk membebankan kaedah? Menggunakan mekanisme refleksi Java untuk membebankan kaedah? Apr 15, 2024 pm 10:54 PM

Mekanisme pantulan digunakan dalam Java untuk melaksanakan kaedah lebih muatan: Dapatkan kaedah melalui refleksi: Gunakan kaedah getMethod() untuk mendapatkan objek kaedah dan nyatakan nama kaedah dan jenis parameter. Kaedah panggilan: Gunakan kaedah invoke() untuk memanggil kaedah, menentukan objek pemanggil dan nilai parameter.

See all articles