2014-02-03 2 views
0

Я имею вопрос создания моего (в основном) обертку общий доступ к даннымПроблема создания общих данных Wrapper

Код

/// <summary> 
/// Get the results of a stronly-typed IList Object 
/// </summary> 
/// <typeparam name="T">Strongly-Typed class of objects that should be returned</typeparam> 
/// <param name="_DBType">The type of database to use</param> 
/// <param name="_Qry">The query to run</param> 
/// <param name="_QryType">The Query Type to run</param> 
/// <param name="_ParamNames">The Parameters' names to pass to the query, if any</param> 
/// <param name="_ParamVals">The Parameters' values to pass to the query, if any</param> 
/// <param name="_ParamDTs">The Parameters' data types to pass to the query, if any</param> 
/// <param name="_ShouldCache">Should we cache the response</param> 
/// <param name="_CacheID">Cache item name</param> 
/// <returns>Strongly Typed ilist of objects</returns> 
public static IList<T> GetResults<T>(Enumerators.DatabaseTypes _DBType, 
            string _Qry, 
            CommandType _QryType, 
            string[] _ParamNames = null, 
            object[] _ParamVals = null, 
            Enumerators.DataTypes[] _ParamDTs = null, 
            bool _ShouldCache = false, 
            string _CacheID = "") where T : new() 
{ 
    // Create a reference to a potential already cached IList 
    IList<T> _CachedItem = _Cache.Get<IList<T>>(_CacheID); 
    // If we're already cached, there's no need to fire up the data access objects, so return the cached item instead 
    if (_CachedItem != null && _ShouldCache) 
    { 
     return _CachedItem; 
    } 
    else 
    { 
     // Fire up our data access object 
     switch (_DBType) 
     { 
      case Enumerators.DatabaseTypes.SqlServer: 
       SqlServer.Access db = new SqlServer.Access(); 
       break; 
      case Enumerators.DatabaseTypes.SqlCE: 
       SqlCE.Access db = new SqlCE.Access(); 
       break; 
      case Enumerators.DatabaseTypes.MySql: 
       MySql.Access db = new MySql.Access(); 
       break; 
      case Enumerators.DatabaseTypes.OLE: 
       Ole.Access db = new Ole.Access(); 
       break; 
      case Enumerators.DatabaseTypes.ODBC: 
       Odbc.Access db = new Odbc.Access(); 
       break; 
      default: 
       db = null; 
     } 
     using (db) 
     { 
      try 
      { 
       // create a new ilist reference of our strongly typed class 
       IList<T> _Query = default(IList<T>); 
       // set the query type 
       db.QueryType = _QryType; 
       // set the query text 
       db.Query = _Qry; 
       // make sure we've got some parameters, if we do the set them to our db access object 
       if (_ParamNames != null) 
       { 
        // set the parameter names 
        db.ParameterNames = _ParamNames; 
        // set the parameter values 
        db.ParameterValues = _ParamVals; 
        // set the parameter data types 
        db.ParameterDataTypes = _ParamDTs; 
       } 
       // start using our db access :) Fire off the GetResults method and return back a SqlDataReader to work on 
       using (DbDataReader r = db.GetResults()) 
       { 
        // make sure the data reader actually exists and contains some results 
        if (r != null) 
        { 
         // map the data reader to our strongly type(s) 
         _Query = Map<T>(r); 
        } 
        r.Close(); 
       } 
       // check if we should cache the results 
       if (_ShouldCache) 
       { 
        // if so, set the query object to the cache 
        _Cache.Set<IList<T>>(_Query, _CacheID); 
       } 
       // return our strongly typed list 
       return _Query; 
      } 
      catch (DbException dEx) 
      { 
       // Catch an exception if any, an write it out to our logging mechanism, in addition to adding it our returnable message property 
       _Msg += "Wrapper.GetResults Exception: " + dEx.Message + db.Message; 
       ErrorReporting.WriteEm.WriteItem(dEx, "o7th.Class.Library.Data.Wrapper.GetResults", _Msg); 
       // make sure this method returns a default List 
       return default(IList<T>); 
      } 
      catch (Exception ex) 
      { 
       // Catch an exception if any, an write it out to our logging mechanism, in addition to adding it our returnable message property 
       _Msg += "Wrapper.GetResults Exception: " + ex.Message + db.Message; 
       ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.Wrapper.GetResults", _Msg); 
       // make sure this method returns a default List 
       return default(IList<T>); 
      } 
     } 
    } 
} 

Access Class - SqlServer

using System; 
using System.Data; 
using System.Data.SqlClient; 
using System.Text; 
using System.Threading.Tasks; 
using System.Xml; 
using System.Xml.Linq; 

namespace o7th.Class.Library.Data.SqlServer 
{ 
internal class Access : IDisposable 
{ 

#region "Properties" 

    // Set the type of query we are running 
    private CommandType _QT; 
    internal CommandType QueryType { set { _QT = value; } } 

    // Set the actual query text to run 
    private string _Qry; 
    internal string Query { set { _Qry = value; } } 

    // Set the parameter names if there are any 
    private string[] _PNs; 
    internal string[] ParameterNames { set { _PNs = value; } } 

    // Set the parameter values if there are any 
    private object[] _PVs; 
    internal object[] ParameterValues { set { _PVs = value; } } 

    // Set the actual Sql Data Types if there are any 
    private DataTypes[] _DTs; 
    internal DataTypes[] ParameterDataTypes { set { _DTs = value; } } 

    // Check to see if there are any parameters passed 
    private bool AreParams() { 
     // Check to see if the values and names are null first 
     if (_PVs != null && _PNs != null) { 
      try { 
       Type _t_pv = _PVs.GetType(); 
       Type _t_pn = _PNs.GetType(); 
       if (_t_pv.IsArray && _t_pn.IsArray) { 
        return (_PVs.Length > 0 && _PNs.Length > 0) ? true : false; 
       } else { 
        return false; 
       } 
      } catch { 
       // yes I meant to do this, we really don't need to get the exception here 
       return false; 
      } 
     } else { 
      return false; 
     } 
    } 

    // Get a return message if any 
    private string _Msg; 
    internal string Message { get { return _Msg; } } 

    // Set the official Sql Reader object 
    private SqlDataReader _Rdr; 
    // Set the official Sql Connection object 
    private SqlConnection _Conn; 
    // Set the official Sql Command object 
    private SqlCommand _Cmd; 
    // Hack for seeing if we're disposed already 
    private bool disposedValue; 

#endregion 

    // Constructor 
    internal Access() { 
     Invoke(); 
    } 

    // Official Constructor. We can thread these 2 becuase they are not being used yet, and it makes it slightly more efficient 
    internal void Invoke() { 
     try { 
      Parallel.Invoke(() => { 
       _Conn = new SqlConnection(AssemblyProperties.GetConnectionString()); 
      },() => 
      { 
       _Cmd = new SqlCommand(); 
      }); 
     } 
     catch (SqlException dEx) 
     { 
      // Catch an exception if any, an write it out to our logging mechanism, in addition to adding it our returnable message property 
      _Msg = "Access.Invoke Exception: " + dEx.Message; 
      ErrorReporting.WriteEm.WriteItem(dEx, "o7th.Class.Library.Data.SqlServer.Access.Invoke", _Msg); 
     } 
     catch (Exception ex) 
     { 
      _Msg = "Access.Invoke Exception: " + ex.Message; 
      ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.Invoke", _Msg); 
     } 
    } 

    /// <summary> 
    /// Return a SqlDataReader based on the properties passed to this class 
    /// </summary> 
    /// <returns></returns> 
    internal SqlDataReader GetResults() 
    { 
     try { 
      // check for parameters 
      if (AreParams()) { 
       PrepareParams(_Cmd); 
      } 
      // set our connection 
      _Cmd.Connection = _Conn; 
      // set the type of query to run 
      _Cmd.CommandType = _QT; 
      // set the actual query to run 
      _Cmd.CommandText = _Qry; 
      // open the connection 
      _Cmd.Connection.Open(); 
      // prepare the command with any parameters that may have gotten added 
      _Cmd.Prepare(); 
      // Execute the SqlDataReader, and set the connection to close once returned 
      _Rdr = _Cmd.ExecuteReader(CommandBehavior.CloseConnection); 
      // clear out any parameters 
      _Cmd.Parameters.Clear(); 
      // return our reader object 
      return (!_Rdr.HasRows) ? null : _Rdr; 
     } 
     catch (SqlException SqlEx) 
     { 
      _Msg += "Acccess.GetResults SqlException: " + SqlEx.Message; 
      ErrorReporting.WriteEm.WriteItem(SqlEx, "o7th.Class.Library.Data.SqlServer.Access.GetResults", _Msg); 
      return null; 
     } 
     catch (Exception ex) { 
      _Msg += "Acccess.GetResults Exception: " + ex.Message; 
      ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.GetResults", _Msg); 
      return null; 
     } 
    } 

    /// <summary> 
    /// Execute a non-return query, and return the success 
    /// </summary> 
    /// <returns></returns> 
    internal bool Execute() { 
     try { 
      // check for parameters 
      if (AreParams()) { 
       PrepareParams(_Cmd); 
      } 
      // set our connection 
      _Cmd.Connection = _Conn; 
      // set the type of query to run 
      _Cmd.CommandType = _QT; 
      // set the actual query to run 
      _Cmd.CommandText = _Qry; 
      // open the connection 
      _Cmd.Connection.Open(); 
      // prepare the command with any parameters that may have gotten added 
      _Cmd.Prepare(); 
      // execute the non-returnable query against the database 
      _Cmd.ExecuteNonQuery(); 
      // clear out any parameters 
      _Cmd.Parameters.Clear(); 
      // executed successfully (otherwise would have thrown an exception) 
      return true; 
     } 
     catch (SqlException SqlEx) 
     { 
      _Msg += "Access.Execute SqlException: " + SqlEx.Message; 
      ErrorReporting.WriteEm.WriteItem(SqlEx, "o7th.Class.Library.Data.SqlServer.Access.Execute", _Msg); 
      return false; 
     } 
     catch (Exception ex) { 
      _Msg += "Access.Execute Exception: " + ex.Message; 
      ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.Execute", _Msg); 
      return false; 
     } 
    } 

    /// <summary> 
    /// Execute a query with a return value. Used in Selecting the ID of the last inserted record. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="_DefVal"></param> 
    /// <returns></returns> 
    internal T ExecuteWithReturn<T>(T _DefVal) { 
     try { 
      T _Ret; 
      // check for parameters 
      if (AreParams()) { 
       PrepareParams(_Cmd); 
      } 
      // set our connection 
      _Cmd.Connection = _Conn; 
      // set the type of query to run 
      _Cmd.CommandType = _QT; 
      // set the actual query to run 
      _Cmd.CommandText = _Qry; 
      // open the connection 
      _Cmd.Connection.Open(); 
      // prepare the command with any parameters that may have gotten added 
      _Cmd.Prepare(); 
      T _T = (T)_Cmd.ExecuteScalar(); 
      _Ret = (_T is DBNull) ? default(T) : _T; 
      // clear out _T 
      _T = default(T); 
      // clear out any parameters 
      _Cmd.Parameters.Clear(); 
      // return the single return value from the query run 
      return _Ret; 
     } 
     catch (SqlException SqlEx) 
     { 
      _Msg += "Access.ExecuteWithReturn SqlException: " + SqlEx.Message; 
      ErrorReporting.WriteEm.WriteItem(SqlEx, "o7th.Class.Library.Data.SqlServer.Access.ExecuteWithReturn", _Msg); 
      return default(T); 
     } catch (Exception ex) { 
      _Msg += "Access.ExecuteWithReturn Exception: " + ex.Message; 
      ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.ExecuteWithReturn", _Msg); 
      return default(T); 
     } 
    } 

    /// <summary> 
    /// Prepare our parameters, adding them and forcing a valid data length 
    /// </summary> 
    /// <param name="objCmd"></param> 
    protected void PrepareParams(SqlCommand objCmd) { 
     try { 
      // set our initial Data Size 
      int _DataSize = 0; 
      // get the number of Parameter Values passed in 
      int _PCt = _PVs.GetUpperBound(0); 
      // begin array check 
      Type _t_dt = _DTs.GetType(); 
      // start looping over our parameters 
      for (int i = 0; i <= _PCt; ++i) { 
       // make sure that the data types are actually an array 
       if (_t_dt.IsArray) { 
        // select which datatype, and force the official size 
        switch ((int)_DTs[i]) { 
         case 0: 
         case 33: 
         case 6: 
         case 9: 
         case 13: 
         case 19: 
          _DataSize = 8; 
          break; 
         case 1: 
         case 3: 
         case 7: 
         case 10: 
         case 12: 
         case 21: 
         case 22: 
         case 23: 
         case 25: 
          _DataSize = _PVs[i].ToString().Length; 
          break; 
         case 2: 
         case 20: 
          _DataSize = 1; 
          break; 
         case 5: 
          _DataSize = 17; 
          break; 
         case 8: 
         case 17: 
         case 15: 
          _DataSize = 4; 
          break; 
         case 14: 
          _DataSize = 16; 
          break; 
         case 31: 
          _DataSize = 3; 
          break; 
         case 32: 
          _DataSize = 5; 
          break; 
         case 16: 
          _DataSize = 2; 
          break; 
        } 
        // add our parameter to the command object 
        objCmd.Parameters.Add(_PNs[i], (SqlDbType)_DTs[i], _DataSize).Value = _PVs[i]; 
       } else { 
        // if the datatypes were not set, try to add them generically 
        objCmd.Parameters.AddWithValue(_PNs[i], _PVs[i]); 
       } 
      } 
      // clean up 
      _PNs = null;_PVs = null;_DTs = null; 
     } catch (Exception ex) { 
      _Msg += "Access.PrepareParams Exception: " + ex.Message; 
      ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.PrepareParams", _Msg); 
     } 
    } 

#region "Dispose Support" 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!disposedValue && disposing) { 
      try 
      { 
       _Qry = string.Empty; 
       _Rdr.Close(); 
       _Rdr.Dispose(); 
       _Cmd.Connection.Close(); 
       _Cmd.Dispose(); 
       if (_Conn.State == ConnectionState.Open) 
       { 
        SqlConnection.ClearAllPools(); 
        _Conn.Close(); 
        _Conn.Dispose(); 
       } 
       _Msg = null; 
      } 
      catch(Exception ex) { 
       ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.SqlServer.Access.Dispose", ""); 
      } 
     } 
     disposedValue = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

#endregion 

} 
} 

Вопрос Я есть, потому что мне нужен оператор switch, чтобы выбрать, какую базу данных использовать метод Access, он бросает The name 'db' does not exist in the current context ошибки на всем протяжении место.

Я также попытался ответить на var db; с сообщением Implicitly-typed local variables.

Я не буду знать, какой тип базы данных будет использоваться до тех пор, пока не настанет время использовать это, поэтому как я могу убедиться, что это работает?

 IDbAccess db; 
     switch (_DBType) 
     { 
      case Enumerators.DatabaseTypes.SqlServer: 
       SqlServer.Access db = new SqlServer.Access(); 
       break; 
      case Enumerators.DatabaseTypes.SqlCE: 
       SqlCE.Access db = new SqlCE.Access(); 
       break; 
      case Enumerators.DatabaseTypes.MySql: 
       MySql.Access db = new MySql.Access(); 
       break; 
      case Enumerators.DatabaseTypes.OLE: 
       Ole.Access db = new Ole.Access(); 
       break; 
      case Enumerators.DatabaseTypes.ODBC: 
       Odbc.Access db = new Odbc.Access(); 
       break; 
      default: 
       db = null; 
     } 

производит Cannot implicitly convert type 'SqlCE.Access to SqlServer.Access' ошибки вниз по линии, а также A local variable 'db' is already defined in this scope и A local variable named 'db' cannot be declared in this scope because it would give a different meaning to 'db' which is already used in a parent of current scope to denote something else

+1

Какой класс/интерфейс SqlServer.Access, SqlCE.Access, MySql.Access, Ole.Access и Odbc.Access наследуют/реализуют? – wdosanjos

+0

Ничего кроме IDisposable. Каждый класс 'Access' каждого типа базы данных делает что-то другое для каждого. – Kevin

+0

. Я выложу один из классов Access в вопросе – Kevin

ответ

2

Все из этих различных поставщиков база данных должны иметь какое-то базовый класс все они наследуют от или интерфейса, который они выполняют. Этот базовый класс/интерфейс должен иметь все операции, которые вы используете позже в методе. Создайте переменную этого базового типа/интерфейса до switch, а затем присвойте этой переменной значение в каждом case.

+0

# 1, не совсем уверен, что вы здесь говорите ... (я C# noob); # 2 Будет ли это применимо и к MySql .Net Connector? – Kevin

+0

@ o7thWebDesign Это довольно простые понятия, поэтому я предлагаю вам провести некоторое исследование терминов, которые вы не знакомы, прежде чем продолжить; это выходит за рамки вопроса SO, чтобы объяснить эти концепции. – Servy