• 基于微软企业库的分层代码框架


    http://blog.csdn.net/zhaoyu008/article/details/6342608

    一般我们都采用分层架构,

    先思考业务,要解决什么样的业务问题,再去思考技术实现。

    l  正向思维:

    界面(UI)—>业务逻辑(BLL)—>数据逻辑(DAL)—>数据实体(Model)—>数据存储(Db)

    l  反向思维:

    数据存储(Db)—>数据实体(Model)—>数据逻辑(DAL)—>业务逻辑(BLL)—>界面(UI)。

    从数据库推导到界面,从界面推导到数据库。搞清楚类之间的关系。数据之间传递关系。

    界面(UI):由控件组成。系统与用户交互的窗口。

    业务逻辑(BLL):封装业务处理功能。对象的组合,应用。

    数据逻辑(DAL):对数据的操作(算法)。(增删改查的多样性),对象函数,方法。

    数据实体(Model):操作的数据结构。对象属性

    数据存储(Db):数据的存储持久化。(表)。

    体会:程序=数据结构+算法,程序=类对象+类对象之间的关系。

     

     

     

    我们的很多项目都是基于微软企业库5.0搭建的。具体说一下我们在企业级项目中是怎么应用的。下面是架构图:

    1.基于微软企业库的工具类

    封装了微软企业库访问数据库常用的最基本的操作。


    2.Model层(数据库表映射)

    封装了很多属性。对应数据库表c_hbbb_code

    代码:

    1. using System;  
    2. namespace SFS.Entity.Model  
    3. {  
    4.     /// summary  
    5.     /// c_hbbb_code  
    6.     /// summary  
    7.     [Serializable]  
    8.     public class c_hbbb_code  
    9.     {  
    10.         public c_hbbb_code()  
    11.         { }  
    12.         private int _CodeID = 0;  
    13.         /// <summary>  
    14.         ///   
    15.         /// </summary>  
    16.         public int CodeID  
    17.         {  
    18.             get { return _CodeID; }  
    19.             set { _CodeID = value; }  
    20.         }  
    21.         private string _CODENO = "";  
    22.         /// <summary>  
    23.         ///   
    24.         /// </summary>  
    25.         public string CODENO  
    26.         {  
    27.             get { return _CODENO; }  
    28.             set { _CODENO = value; }  
    29.         }  
    30.         private string _CODENAME = "";  
    31.         /// <summary>  
    32.         ///   
    33.         /// </summary>  
    34.         public string CODENAME  
    35.         {  
    36.             get { return _CODENAME; }  
    37.             set { _CODENAME = value; }  
    38.         }  
    39.         private string _ISMX = "";  
    40.         /// <summary>  
    41.         ///   
    42.         /// </summary>  
    43.         public string ISMX  
    44.         {  
    45.             get { return _ISMX; }  
    46.             set { _ISMX = value; }  
    47.         }  
    48.         private string _ParentCodeNO = "";  
    49.         /// <summary>  
    50.         ///   
    51.         /// </summary>  
    52.         public string ParentCodeNO  
    53.         {  
    54.             get { return _ParentCodeNO; }  
    55.             set { _ParentCodeNO = value; }  
    56.         }  
    57.         private string _ZT = "";  
    58.         /// <summary>  
    59.         ///   
    60.         /// </summary>  
    61.         public string ZT  
    62.         {  
    63.             get { return _ZT; }  
    64.             set { _ZT = value; }  
    65.         }  
    66.     }  
    67. }  


    3.Dal层(封装数据库操作增,删,改,查)

     

    1. namespace SFS.DAL  
    2. {  
    3.     public class c_hbbb_code  
    4.     {  
    5.   
    6.   
    7.         private SFS.Utility.DbUtility.DbHelper db = null;  
    8.   
    9.         /// <summary>  
    10.         /// 是否存在该记录  
    11.         /// </summary>  
    12.         public bool Exists(string CodeID)  
    13.         {  
    14.             
    15.             string strSql = "SELECT count(1) FROM c_hbbb_code WHERE  CodeID=@CodeID ";  
    16.             DbCommand dbCommand = db.GetSqlStringCommand(strSql);  
    17.             db.AddInParameter(dbCommand, "CodeID", DbType.String, CodeID);  
    18.   
    19.             int result;  
    20.             object obj = db.ExecuteScalar(dbCommand);  
    21.             int.TryParse(obj.ToString(), out result);  
    22.             if (result == 1)  
    23.             {  
    24.                 return true;  
    25.             }  
    26.             else  
    27.             {  
    28.                 return false;  
    29.             }  
    30.         }  
    31.   
    32.   
    33.         /// <summary>  
    34.         ///  增加一条数据  
    35.         /// </summary>  
    36.         public int Add(SFS.Entity.Model.c_hbbb_code model)  
    37.         {  
    38.             return Add(model, null);  
    39.         }  
    40.   
    41.         /// <summary>  
    42.         ///  增加一条数据  
    43.         /// </summary>  
    44.         public int Add(SFS.Entity.Model.c_hbbb_code model, DbTransaction transaction)  
    45.         {  
    46.             try  
    47.             {  
    48.                 string strSql = "INSERT INTO c_hbbb_code(CodeID,CODENO,CODENAME,ISMX,ParentCodeNO,ZT)VALUES(@CodeID,@CODENO,@CODENAME,@ISMX,@ParentCodeNO,@ZT)";  
    49.                 DbCommand dbCommand = db.GetSqlStringCommand(strSql);  
    50.                 db.AddInParameter(dbCommand, "CodeID", DbType.Int32, model.CodeID);  
    51.                 db.AddInParameter(dbCommand, "CODENO", DbType.String, model.CODENO);  
    52.                 db.AddInParameter(dbCommand, "CODENAME", DbType.String, model.CODENAME);  
    53.                 db.AddInParameter(dbCommand, "ISMX", DbType.String, model.ISMX);  
    54.                 db.AddInParameter(dbCommand, "ParentCodeNO", DbType.String, model.ParentCodeNO);  
    55.                 db.AddInParameter(dbCommand, "ZT", DbType.String, model.ZT);  
    56.   
    57.                 if (transaction == null)  
    58.                 {  
    59.                     return db.ExecuteNonQuery(dbCommand);  
    60.                 }  
    61.                 else  
    62.                 {  
    63.                     return db.ExecuteNonQuery(dbCommand, transaction);  
    64.                 }  
    65.             }  
    66.             catch (AddException addex)  
    67.             {  
    68.                 addex.DeveloperMessage = "添加c_hbbb_code记录失败!" + addex.Message + "在" + this.ToString() + ".Add(SFS.Entity.Model.c_hbbb_code model)中";  
    69.                 addex.UserMessage = "添加c_hbbb_code记录失败!";  
    70.                 throw addex;  
    71.             }  
    72.         }  
    73.   
    74.         /// <summary>  
    75.         ///  更新一条数据  
    76.         /// </summary>  
    77.         public int Update(SFS.Entity.Model.c_hbbb_code model)  
    78.         {  
    79.             return Update(model, null);  
    80.         }  
    81.   
    82.         /// <summary>  
    83.         ///  更新一条数据  
    84.         /// </summary>  
    85.         public int Update(SFS.Entity.Model.c_hbbb_code model, DbTransaction transaction)  
    86.         {  
    87.             try  
    88.             {  
    89.                 string strSql = "UPDATE c_hbbb_code SET CODENO=@CODENO,CODENAME=@CODENAME,ISMX=@ISMX,ParentCodeNO=@ParentCodeNO,ZT=@ZT  WHERE  CodeID=@CodeID ";  
    90.                 DbCommand dbCommand = db.GetSqlStringCommand(strSql);  
    91.                 db.AddInParameter(dbCommand, "CodeID", DbType.Int32, model.CodeID);  
    92.                 db.AddInParameter(dbCommand, "CODENO", DbType.String, model.CODENO);  
    93.                 db.AddInParameter(dbCommand, "CODENAME", DbType.String, model.CODENAME);  
    94.                 db.AddInParameter(dbCommand, "ISMX", DbType.String, model.ISMX);  
    95.                 db.AddInParameter(dbCommand, "ParentCodeNO", DbType.String, model.ParentCodeNO);  
    96.                 db.AddInParameter(dbCommand, "ZT", DbType.String, model.ZT);  
    97.   
    98.                 if (transaction == null)  
    99.                 {  
    100.                     return db.ExecuteNonQuery(dbCommand);  
    101.                 }  
    102.                 else  
    103.                 {  
    104.                     return db.ExecuteNonQuery(dbCommand, transaction);  
    105.                 }  
    106.             }  
    107.             catch (UpdateException updateex)  
    108.             {  
    109.                 updateex.DeveloperMessage = "修改c_hbbb_code记录失败!" + updateex.Message + "在" + this.ToString() + ".Update(SFS.Entity.Model.c_hbbb_code model)中";  
    110.                 updateex.UserMessage = "修改c_hbbb_code记录失败!";  
    111.                 throw updateex;  
    112.             }  
    113.         }  
    114.   
    115.         /// <summary>  
    116.         /// 删除一条数据  
    117.         /// </summary>  
    118.         public int Delete(string CodeID)  
    119.         {  
    120.             return Delete(CodeID, null);  
    121.         }  
    122.   
    123.         /// <summary>  
    124.         /// 删除一条数据  
    125.         /// </summary>  
    126.         public int Delete(string CodeID, DbTransaction transaction)  
    127.         {  
    128.             try  
    129.             {  
    130.                 if (string.IsNullOrEmpty(CodeID))  
    131.                 {  
    132.                     NOIsNullOrEmptyException exception = new NOIsNullOrEmptyException();  
    133.                     exception.DeveloperMessage = "CodeID编号不能为空!在" + this.ToString() + ".Delete(string CodeID)中";  
    134.                     exception.UserMessage = "CodeID编号不能为空!";  
    135.                     throw exception;  
    136.                 }  
    137.   
    138.   
    139.                 string strSql = "DELETE FROM c_hbbb_code WHERE  CodeID=@CodeID ";  
    140.                 DbCommand dbCommand = db.GetSqlStringCommand(strSql);  
    141.                 db.AddInParameter(dbCommand, "CodeID", DbType.String, CodeID);  
    142.   
    143.                 if (transaction == null)  
    144.                 {  
    145.                     return db.ExecuteNonQuery(dbCommand);  
    146.                 }  
    147.                 else  
    148.                 {  
    149.                     return db.ExecuteNonQuery(dbCommand, transaction);  
    150.                 }  
    151.             }  
    152.             catch (DeleteException deleteex)  
    153.             {  
    154.                 deleteex.DeveloperMessage = "删除c_hbbb_code记录失败!" + deleteex.Message + "在" + this.ToString() + ".Delete(string CodeID)中";  
    155.                 deleteex.UserMessage = "删除c_hbbb_code记录失败!";  
    156.                 throw deleteex;  
    157.             }  
    158.         }  
    159.   
    160.         /// <summary>  
    161.         /// 得到一个对象实体  
    162.         /// </summary>  
    163.         public SFS.Entity.Model.c_hbbb_code GetModel(string CodeID)  
    164.         {  
    165.             if (string.IsNullOrEmpty(CodeID))  
    166.             {  
    167.                 NOIsNullOrEmptyException exception = new NOIsNullOrEmptyException();  
    168.                 exception.DeveloperMessage = "CodeID编号不能为空!在" + this.ToString() + ".GetModel(string CodeID)中";  
    169.                 exception.UserMessage = "CodeID编号不能为空!";  
    170.                 throw exception;  
    171.             }  
    172.   
    173.             StringBuilder strSql = new StringBuilder();  
    174.             strSql.Append("SELECT CodeID,CODENO,CODENAME,ISMX,ParentCodeNO,ZT ");  
    175.             strSql.Append(" FROM c_hbbb_code ");  
    176.             strSql.Append(" WHERE  CodeID=@CodeID ");  
    177.   
    178.             DbCommand dbCommand = db.GetSqlStringCommand(strSql.ToString());  
    179.             db.AddInParameter(dbCommand, "CodeID", DbType.String, CodeID);  
    180.   
    181.   
    182.             SFS.Entity.Model.c_hbbb_code model = null;  
    183.             using (IDataReader dataReader = db.ExecuteReader(dbCommand))  
    184.             {  
    185.                 if (dataReader.Read())  
    186.                 {  
    187.                     model = ReaderBind(dataReader);  
    188.                 }  
    189.             }  
    190.             return model;  
    191.         }  
    192.   
    193.         /// <summary>  
    194.         /// 获得数据列表  
    195.         /// </summary>  
    196.         public DataSet GetDataSet(string strWhere)  
    197.         {  
    198.             try  
    199.             {  
    200.                 StringBuilder strSql = new StringBuilder();  
    201.                 strSql.Append("SELECT CodeID,CODENO,CODENAME,ISMX,ParentCodeNO,ZT ");  
    202.                 strSql.Append(" FROM c_hbbb_code ");  
    203.                 if (strWhere.Trim() != "")  
    204.                 {  
    205.                     strSql.Append(" WHERE " + strWhere);  
    206.                 }  
    207.                 return db.ExecuteDataSet(CommandType.Text, strSql.ToString());  
    208.             }  
    209.             catch (SelectException selectex)  
    210.             {  
    211.                 selectex.DeveloperMessage = "查询记录失败!" + selectex.Message + "在" + this.ToString() + ".GetDataSet(string strWhere)中";  
    212.                 selectex.UserMessage = "查询记录失败!";  
    213.                 throw selectex;  
    214.             }  
    215.         }  
    216.   
    217.         /// <summary>  
    218.         /// 获得数据列表(比DataSet效率高,推荐使用)  
    219.         /// </summary>  
    220.         public List<SFS.Entity.Model.c_hbbb_code> GetList(string strWhere)  
    221.         {  
    222.             try  
    223.             {  
    224.                 StringBuilder strSql = new StringBuilder();  
    225.                 strSql.Append("SELECT CodeID,CODENO,CODENAME,ISMX,ParentCodeNO,ZT ");  
    226.                 strSql.Append(" FROM c_hbbb_code ");  
    227.                 if (strWhere.Trim() != "")  
    228.                 {  
    229.                     strSql.Append(" WHERE " + strWhere);  
    230.                 }  
    231.                 List<SFS.Entity.Model.c_hbbb_code> list = new List<SFS.Entity.Model.c_hbbb_code>();  
    232.                 using (IDataReader dataReader = db.ExecuteReader(CommandType.Text, strSql.ToString()))  
    233.                 {  
    234.                     while (dataReader.Read())  
    235.                     {  
    236.                         list.Add(ReaderBind(dataReader));  
    237.                     }  
    238.                 }  
    239.                 return list;  
    240.             }  
    241.             catch (SelectException selectex)  
    242.             {  
    243.                 selectex.DeveloperMessage = "查询记录失败!" + selectex.Message + "在" + this.ToString() + ".GetList(string strWhere)中";  
    244.                 selectex.UserMessage = "查询记录失败!";  
    245.                 throw selectex;  
    246.             }  
    247.         }  
    248.   
    249.   
    250.         /// <summary>  
    251.         /// 对象实体绑定数据  
    252.         /// </summary>  
    253.         public SFS.Entity.Model.c_hbbb_code ReaderBind(IDataReader dataReader)  
    254.         {  
    255.             SFS.Entity.Model.c_hbbb_code model = new SFS.Entity.Model.c_hbbb_code();  
    256.             object obj;  
    257.   
    258.             obj = dataReader["CodeID"];  
    259.             if (obj != null && obj != DBNull.Value)  
    260.             {  
    261.                 model.CodeID = (int)obj;  
    262.             }  
    263.   
    264.             obj = dataReader["CODENO"];  
    265.             if (obj != null && obj != DBNull.Value)  
    266.             {  
    267.                 model.CODENO = obj.ToString();  
    268.             }  
    269.   
    270.             obj = dataReader["CODENAME"];  
    271.             if (obj != null && obj != DBNull.Value)  
    272.             {  
    273.                 model.CODENAME = obj.ToString();  
    274.             }  
    275.   
    276.             obj = dataReader["ISMX"];  
    277.             if (obj != null && obj != DBNull.Value)  
    278.             {  
    279.                 model.ISMX = obj.ToString();  
    280.             }  
    281.   
    282.             obj = dataReader["ParentCodeNO"];  
    283.             if (obj != null && obj != DBNull.Value)  
    284.             {  
    285.                 model.ParentCodeNO = obj.ToString();  
    286.             }  
    287.   
    288.             obj = dataReader["ZT"];  
    289.             if (obj != null && obj != DBNull.Value)  
    290.             {  
    291.                 model.ZT = obj.ToString();  
    292.             }  
    293.   
    294.             return model;  
    295.         }  
    296.   
    297.       }  
    298. }  


    4.Bll层(跟具体业务有关的逻辑)

     

    1. namespace SFS.BLL  
    2. {  
    3.     /// <summary>  
    4.     /// 业务逻辑类bllADDRESS 的摘要说明。  
    5.     /// </summary>  
    6.     public class c_hbbb_code  
    7.     {  
    8.         private readonly SFS.DAL.c_hbbb_code dal = new SFS.DAL.c_hbbb_code();  
    9.         public c_hbbb_code()  
    10.         { }  
    11.         #region  成员方法  
    12.         /// <summary>  
    13.         /// 是否存在该记录  
    14.         /// </summary>  
    15.         public bool Exists(string CodeID)  
    16.         {  
    17.             try  
    18.             {  
    19.                 return dal.Exists(CodeID);  
    20.             }  
    21.             catch (ExceptionBase ex)  
    22.             {  
    23.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    24.                 return false;  
    25.             }  
    26.         }  
    27.   
    28.         /// <summary>  
    29.         /// 增加一条数据  
    30.         /// </summary>  
    31.         public int Add(SFS.Entity.Model.c_hbbb_code model)  
    32.         {  
    33.             try  
    34.             {  
    35.                 return dal.Add(model);  
    36.             }  
    37.             catch (ExceptionBase ex)  
    38.             {  
    39.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    40.                 return 0;  
    41.             }  
    42.         }  
    43.   
    44.         /// <summary>  
    45.         /// 更新一条数据  
    46.         /// </summary>  
    47.         public int Update(SFS.Entity.Model.c_hbbb_code model)  
    48.         {  
    49.             try  
    50.             {  
    51.                 return dal.Update(model);  
    52.             }  
    53.             catch (ExceptionBase ex)  
    54.             {  
    55.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    56.                 return 0;  
    57.             }  
    58.         }  
    59.   
    60.         /// <summary>  
    61.         /// 删除一条数据  
    62.         /// </summary>  
    63.         public int Delete(string CodeID)  
    64.         {  
    65.             try  
    66.             {  
    67.                 return dal.Delete(CodeID);  
    68.             }  
    69.             catch (ExceptionBase ex)  
    70.             {  
    71.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    72.                 return 0;  
    73.             }  
    74.         }  
    75.   
    76.         /// <summary>  
    77.         /// 得到一个对象实体  
    78.         /// </summary>  
    79.         public SFS.Entity.Model.c_hbbb_code GetModel(string CodeID)  
    80.         {  
    81.             try  
    82.             {  
    83.                 return dal.GetModel(CodeID);  
    84.             }  
    85.             catch (ExceptionBase ex)  
    86.             {  
    87.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    88.                 return null;  
    89.             }  
    90.         }  
    91.   
    92.   
    93.         /// <summary>  
    94.         /// 获得数据列表  
    95.         /// </summary>  
    96.         public DataSet GetDataSet(string strWhere)  
    97.         {  
    98.             try  
    99.             {  
    100.                 return dal.GetDataSet(strWhere);  
    101.             }  
    102.             catch (ExceptionBase ex)  
    103.             {  
    104.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    105.                 return null;  
    106.             }  
    107.         }  
    108.   
    109.         /// <summary>  
    110.         /// <summary>  
    111.         /// 获得数据列表  
    112.         /// </summary>  
    113.         public List<SFS.Entity.Model.c_hbbb_code> GetList(string strWhere)  
    114.         {  
    115.             try  
    116.             {  
    117.                 return dal.GetList(strWhere);  
    118.             }  
    119.             catch (ExceptionBase ex)  
    120.             {  
    121.                 SFS.Utility.ExceptionUtility.ExceptionHelper.HandleException(ex, Policy.BLLPolicy);  
    122.                 return null;  
    123.             }  
    124.         }  
    125.        
    126.        
    127.         #endregion  成员方法  
    128.   
    129.        
    130.   
    131.     }  
    132. }  


    5.UI层(用户界面)

     

    常用界面功能代码

    界面模式:单选(新建,删除,修改,查看)

    功能名称

    查询 新建 删除 修改 查看

    数据列表

    加载数据

     

    分页

     

    自动加入序号

     

    添加

     

    删除

     

    修改

     

    查看

     

    导出

     

    加载数据

    private void LoadData(string SJJG)

    {

    SFS.Bll.c_hbbb_codeobjC_SUBCOMPANY=new SFS.Bll.c_hbbb_code();

    this.GridView1.DataSource = objC_SUBCOMPANY.GetList(“”);

    this.GridView1.DataBind();

    }

    分页

    protected voidGridView1_PageIndexChanging(objectsender,GridViewPageEventArgs e)

    {

    this.GridView1.PageIndex = e.NewPageIndex;

    LoadData(“”);

    }

    绑定时自动加入序号

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)

    {

          if (e.Row.RowType == DataControlRowType.DataRow)

          {

    RadioButton rb = (RadioButton)e.Row.FindControl("rbSelect");

    rb.Attributes.Add("onclick", "CheckOne(this);");

    e.Row.Cells[1].Text = Convert.ToString(e.Row.RowIndex + 1);

           }

    }

    添加

    protected void btnAdd_Click(object sender, EventArgs e)

    {

        Response.Redirect("Add.aspx?JGDM=" + SJJG);

    }

    删除

    protected void btnUpdate_Click(object sender, EventArgs e)

    {

        foreach (GridViewRow row in GridView1.Rows)

        {

    RadioButton radio = row.FindControl("rbSelect") as RadioButton;

    if (radio != null && radio.Checked)

    {

           Label lblID = (Label)row.FindControl("lblJGDM");

           Response.Redirect("Delete.aspx?JGDM=" + SJJG);

           break;

            }

    }

    }

     

    修改

    protected void btnUpdate_Click(object sender, EventArgs e)

    {

        foreach (GridViewRow row in GridView1.Rows)

        {

    RadioButton radio = row.FindControl("rbSelect") as RadioButton;

    if (radio != null && radio.Checked)

    {

           Label lblID = (Label)row.FindControl("lblJGDM");

           Response.Redirect("Update.aspx?JGDM=" + SJJG);

           break;

            }

    }

    }

    一般写界面代码逻辑顺序

    步骤

     

     

     

    1

    Page_Load

    中判断Session是否超时。

     

    获取页面参数。

     

    加载初始化控件(DropDownList,TextBox等控件)。

    调用BBL层。

    执行初始化查询绑定GridView控件。

    调用BBL层。

    2

    Button_Click

    判断界面参数设置数据有效性

    脚本判断,或页面上后台代码判断。

    处理数据一般包括。

    增加:跳转到增加页面。

    删除:删除前要提示。

    修改:先判断是否选中,跳转到修改页面,需要传递参数。

    查询:先检查查询条件的有效性,再执行查询。

     

    调用BLL层

    判断是否刷新页面。

     

    3

    GridView

    一般性代码(分页,加单选,多选处理,绑定超连接,特殊列处理)

     

    获得选种行,传递相关参数。

     

    4

    其他特殊处理

     

     

  • 相关阅读:
    现代软件工程_第一周练习_第12题
    [assembly: AssemblyVersion("1.0.1.*")] 指定版本字符串不符合所需格式
    C#中结构体与字节流互相转换
    字节转化为结构体BytesToStruct
    C#调用Microsoft.DirectX.DirectSound问题记录及解决
    C# Wpf集合双向绑定
    <转载>XML操作
    <转载>提升程序的特权(AdjustTokenPrivileges)
    <转载>批处理之FOR语句祥解
    Effective STL 笔记: Item 6--Be alert for C++'s most vexing parse
  • 原文地址:https://www.cnblogs.com/swarb/p/9924253.html
Copyright © 2020-2023  润新知