C# 应用 - 数据库适配

1. 逻辑

  1. 封装各个数据库的访问方式;
  2. 以表为单位,定义 interface 接口,实现增删改查等操作,基于 Postgresql、Oracel 等数据库的具体实现类继承 interface;
  3. 封装 DataAccess 类,实现访问数据库的统一入口,通过反射的方式实现;
    对 Postgresql、Oracel 等数据库的具体实现类的类名有要求。
    如:PgStudent、OracleStudent,前缀固定为 Pg、Oracle,后缀保持一致。
  4. 封装对接业务层的 Model 层,通过 DataAccess 获取对应的数据库、数据表,返回给业务层。

2. 文件结构

3. 代码示例

3.1 interface 接口及具体实现类

public class Student {}

public interface IStudent
{
    /// <summary>
    /// 获取学生列表
    /// </summary>
    /// <returns></returns>
    List<Student> GetStudentList(int page, int size);
}

/// <summary>
/// 从 Pg 表操作 学生 表
/// </summary>
public class PgStudent : AbstractPostgresql, IStudent
{
    public List<Student> GetStudentList(int page, int size) 
    {
        var list = new List<Student>();
        try
        {
            string selectSql = string.Format("SELECT ...;");
            var dt = this.ExecuteQuery(selectSql); //执行 sql 语句
            list = DataTableToList<Student>(dt).ToList();//转成集合
        }
        catch (Exception ex) {}
        
        return list;
    }
}

/// <summary>
/// 从 Oracle 操作 学生 表
/// </summary>
public class OracleStudent : AbstractOracle, IStudent
{
    public List<Student> GetStudentList(int page, int size) 
    {
        var list = new List<Student>();
        try
        {
            string selectSql = string.Format("SELECT ...;");
            var dt = this.ExecuteQuery(selectSql);
            list = DataTableToList<Student>(dt).ToList();
        }
        catch (Exception ex) {}
        
        return list;
    }
}

AbstractPostgresql 参考 https://www.cnblogs.com/MichaelLoveSna/p/14478846.html
AbstractOracle 参考 https://www.cnblogs.com/MichaelLoveSna/p/14478879.html

3.2 DataAccess

通过反射的方式,根据配置文件决定的

public class DataAccess
{
    private static readonly string AssemblyName = "GoSun.VMapEngine.Vmap.YunXing";

    private static readonly string db = ConfigurationManager.AppSettings["DBType"];

    private static object _iStudentLockObj = new object();
    private static IStudent _iStudent;

    private static object _iTeacherLockObj = new object();
    private static ITeacher _iTeacher;
    
    ...
    
    /// <summary>
    /// 获取学生操作类,使用单例模式(双锁)
    /// </summary>
    /// <returns></returns>
    public static IStudent CreateStudent()
    {            
        if (_iStudent == null)
        {
            lock (_iStudentLockObj)
            {
                if (_iStudent == null)
                {
                    string className = AssemblyName + "." + db + "Student";
                    _iStudent = (IStudent)Assembly.Load(AssemblyName).CreateInstance(className);
                }
            }                
        }

        return _iStudent;
    }
}

3.3 GetStudent.cs

调用 DataAccess,根据配置文件制定的数据库类型获取对应的 Student 的数据库操作类,然后调用类的方法进行 sql 语句的操作。

public class GetStudentInfo
{
    #region 获取学生列表
    /// <summary>
    /// 获取列表列表
    /// </summary>
    /// <returns></returns>
    public static List<Student> GetStudentList(int page, int size)
    {
        List<Student> stuList = null;
        
        IStudent iStu = DataAccess.CreateStudent();
        stuList = iStu.GetStudentList(int page, int size);

        return stuList;
    }

    /// <summary>
    /// 异步获取学生列表
    /// </summary>
    /// <returns></returns>
    public async static Task<List<Student>> AsyncGetStudentList(int page, int size)
    {
        List<Student> stuList = await Task.Run(() =>
        {
            IStudent iStu = DataAccess.CreateStudent();
            return iStu.GetStudentList(int page, int size);
        });

        return stuList;
    }

    #endregion

}

3.4 业务调用

public class x
{
    public async void InitStuList()
    {
        int page = 1;
        int size = 10;
        List<Student> stuList = await GetStudentInfo.AsyncGetStudentList(int page, int size);
    
        // To do 
        // use stuList
    }
    
    
    public void InitStuList_2()
    {
        int page = 1;
        int size = 10;
        Task.Run(() =>
        {
            return GetStudentInfo.AsyncGetStudentList(int page, int size);
        }).ContinueWith((r) =>
        {
            // To do 
            // use r.Result
        });             
    }
}
posted @ 2021-03-13 11:09  鑫茂  阅读(60)  评论(0编辑  收藏  举报