65.9K
CodeProject 正在变化。 阅读更多。
Home

JDAC - 数据访问及更多

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2019年7月30日

CPOL

10分钟阅读

viewsIcon

9252

JDAC是一个优秀的替代Entity Framework的数据访问组件,因为它具有更高的支持和维护成本。

引言

JDAC是一个.NET Standard 2.0库组件,可用于任何.NET项目,无论是Core还是Standard,在任何支持的操作系统上访问SQL Server。该库提供了灵活易用的访问方式来执行SQL查询或执行不返回数据集的SQL。还内置了一些用于获取模式信息的查询,以及将System.Data.DataTable对象转换为各种用途的方法,包括域对象类(C#)。

背景

访问SQL Server数据库并不难,但代码很重复。我创建JDAC是因为我看到了Entity Framework (EF) 在软件开发项目的支持和维护阶段的脆弱性和复杂性,尤其是在数据库模式更改并影响使用EF的代码时。我发现,总体而言,创建自己的模式文件、存储过程等并使数据访问通用化,所花费的时间更少。在此过程中,我厌倦了编写简单的域对象类来保存查询数据或发送更新。因此,我在JDAC中添加了方法调用,可以将任何给定的数据表转换为匹配域对象的C#代码,以及用于填充同一域对象的独立C#代码。虽然可以使用JDAC而无需此功能,但它可能很有帮助。

Using the Code

理解DBReturnValue对象

在执行任何类型的查询时,都有机会不仅仅是执行查询。可能存在返回参数或返回码。如果出现问题并抛出异常,通常会有多个异常层可以检查以进行故障排除。
DBReturnValue具有几个处理这些问题和任何返回的System.Data.Dataset的属性。该类标记为“[Serializable]”。

构造函数

DBReturnValue()

类的默认构造函数。

DBReturnValue(List<SqlParameter> sqlParams, Int32 retCode, String errorMessage)

用于提供SQL参数、返回码和错误消息(如果有)的构造函数。此构造函数通常在内部使用。

属性

List<SqlParameter> - (Get/Set)

传入的参数,在执行后,参数会为任何输出参数进行更新。

Int32 RetCode – (Get/Set)

查询执行的返回码。它可以是受影响的记录数,或代表状态的值,具体取决于所执行SQL的类型。如果它是“执行无查询”SQL,则RetCode是受影响的记录数。

String ErrorMessage – (Get/Set)

SQL执行返回的错误消息。如果没有异常,则为空string

System.Data.DataSet Data – (Get/Set)

对于返回数据的调用,这是返回的dataset

方法

Dispose()

通常在Finally块中调用,以释放对象实例所拥有的任何资源。内部标志可确保内部Dispose过程仅调用一次。还有一个用于垃圾回收器的终结器方法。

理解JDataAccessSQL对象

JDataAccessSQL对象是访问SQL Server数据的“主力”。

构造函数

JDataAccessSQL()

默认构造函数

JDataAccessSQL(String server,
               String defaultDB,
               Boolean useAuthentication,
               String username,
               String password,
               Int32 connectionTimeout,
               Int32 commandTimeout,
               Int32 connectRetryCount = 3,
               Int32 connectRetryInterval = 10,
               String applicationName = "",
               String workstationID = "",
               Int32 portNumber = 1433,
               Boolean connectionPooling = true)

此构造函数接受连接SQL Server所需的所有必需和可选数据点。最后六个参数提供默认值,以防您接受这些值。当useAuthentication = true时,用户名和密码使用空string。如果您使用其他值,它们将被忽略。

有关参数的详细信息,请参阅下面的匹配属性。

属性

  • String Server - (Get/Set):服务器名称,包括实例名称(如果使用)
  • String DefaultDB - (Get/Set):连接字符串中用作默认值的数据库
  • Boolean UseAuthentication - (Get/Set):是否使用Windows身份验证。True表示使用,false表示使用用户名和密码
  • String UserName - (Get/Set):如果**不**使用Windows身份验证,则使用的用户名
  • String Password - (Get/Set):如果**不**使用Windows身份验证,则使用的密码
  • Int32 ConnectionTimeout - (Get/Set):连接对象等待超时异常的秒数
  • Int32 CommandTimeout - (Get/Set):命令对象在超时前等待不活动命令执行的秒数
  • Int32 PortNumber - (Get/Set)
  • 连接SQL Server的端口号。如果为0或更小,则使用端口1433。默认值为1433。
  • Int32 ConnectRetryCount - (Get/Set):在抛出异常之前尝试重新连接的次数。默认为3。另请参阅ConnectRetryInterval
  • Int32 ConnectRetryInterval - (Get/Set):重新连接尝试之间等待的秒数。默认为10。另请参阅ConnectRetryCount
  • String ApplicationName - (Get/Set):使用此连接的应用程序的可选名称。SQL Server使用此值。默认值为空string
  • String WorkstationID - (Get/Set):一个ID string,标识连接来自的工作站。此项是可选的。默认值为空string
  • Boolean UseConnectionPooling – (Get/Set)True表示使用连接池(默认),false表示不使用
  • String ConnectionString – (Get):只读连接string

方法及示例

  • async Task<Boolean> CheckConnectionAsync()

    一个true/false检查,用于查看是否可以建立连接。

    //Code example:
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                            "CookieStore", true, "", "",
                                            10, 20, 3, 10, "MyProgram",
                                            "MyComputer", 20161, true);
    Boolean retVal = dac.CheckConnectionAsync().Result;
    dac.Dispose();
    dac = null;
  • async Task<DBReturnValue> ExecuteQueryAsync(String cmd, // SQL Command
    Boolean isSP,                 // 如果是存储过程,则为True,否则为False
    List<SqlParameter> sqlParams) // 参数对象列表,或
                                  // 如果不使用参数,则为null。

    异步方法,用于执行查询并返回数据。返回DBReturnValue实例,其中包含结果和执行后具有值的参数。

    //Code Example:
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    String cmd = "SELECT * FROM dbo.Cookies WHERE ID > @id";
    List<SqlParameter> queryParams = new List<SqlParameter>();
    queryParams.Add(new SqlParameter
                   {
                   DbType = DbType.Int64,
                   ParameterName = "@id",
                   Value = 0
                   });
    DBReturnValue dbRetVal = dac.ExecuteQueryAsync(cmd, false, queryParams).Result;
    DataSet retVal = dbRetVal.Data;
    dac.Dispose();
    dac = null;
  • async Task<DBReturnValue> ExecuteStatementAsync(String cmd,  // SQL Command Boolean isSP,                 // 如果是存储过程,则为True,否则为False List<SqlParameter> sqlParams) // 参数对象列表

    异步方法,用于执行不返回数据集的SQL。返回DBReturnValue实例,其中包含结果和执行后具有值的参数。

    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    String cmd = "UPDATE dbo.Cookies SET Name='Raspberry' WHERE ID = @id";
    List<SqlParameter> queryParams = new List<SqlParameter>();
    queryParams.Add(new SqlParameter
    {
      DbType = DbType.Int64,
      ParameterName = "@id",
      Value = 1
    });
    DBReturnValue dbRetVal = dac.ExecuteStatementAsync(cmd, false, queryParams).Result;
    dac.Dispose();
    dac = null;
  • async Task<SQLServerData> GetServerPropertiesAsync()

    异步方法,用于查询SQL Server属性上的数据。SQLServerData是可序列化的,并且具有数据契约。SQLServerData类中的属性是

    • String SvrName
    • String ServerMachineName
    • String EditionName
    • String ProductVersion
    • String ProductLevel
    • String LicenseType
    • Boolean IsIntegratedSecurityOnly
    • Boolean IsClustered
    • String Language
    • String Platform
    • String Description
    • Int32 ProcessorsCount
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    SQLServerData retVal = dac.GetServerPropertiesAsync().Result;
    dac.Dispose();
    dac = null;
  • async Task<List<String>> GetDatabaseNamesAsync()

    异步方法,用于获取数据库名称列表。通过使用GetSchema(SchemaTypesEnum.Databases)方法可以获得更完整的数据。此方法返回数据库名称的string列表。

    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    List<String> retVal = dac.GetDatabaseNamesAsync().Result;
    dac.Dispose();
    dac = null;
  • async Task<DataTable> GetDatabaseRelationshipsAsync(String targetDatabase = "")

    异步方法,用于获取指定数据库中的关系列表。默认数据库是连接字符串中指定的数据库。返回一个带有关系数据的System.Data.DataTable。列全部是String,名称如下:

    • Foriegn_Key_Name
    • Parent_Table
    • Primary_Key_Column
    • Child_Table
    • Foriegn_Key_Column
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    DataTable retVal = dac.GetDatabaseRelationshipsAsync("Test").Result;
    dac.Dispose();
    dac = null;
  • async Task<List<String>> GetTableNamesAsync(String targetDatabase = "")

    异步方法,用于获取指定数据库的表名称,或默认使用连接字符串中指定的数据库。该方法返回指定数据库的表名称列表,或默认返回连接string中命名的数据库。

    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    List<String> retVal = dac.GetTableNamesAsync().Result;
    dac.Dispose();
    dac = null;
  • async Task<DataTable> GetSchemaAsync(SchemaTypesEnum schemaType, String targetDatabase = "")

    异步方法,根据请求的模式类型获取模式元素数据。该方法返回一个带有模式定义的DataTableDataTable列根据每个模式类型而变化。您可以使用SchemaFactory对象获取与可序列化对象相同的模式信息,这些对象具有特定于模式类型的属性。

SchemaTypesEnum

  • Unspecified - 默认值
  • MetaDataCollections - 列出已知模式的名称
  • DataSourceInformation = SQL Server信息
  • DataTypes = SQL Server数据类型和信息的列表,以及它们的.NET对应项
  • ReservedWords - 此服务器上T-SQL中的保留字列表。
  • Users - 数据库用户列表
  • Databases - 服务器上的数据库列表
  • Tables - 连接字符串中指定的数据库的表列表
  • Columns - 连接字符串中指定的数据库的表的所有列列表
  • AllColumns - 功能上与上面的Columns相同,但可能提供通常不可用的其他列
  • ColumnSetColumns - ColumnSets(SQL 2016及更高版本)
  • StructuredTypeMembers - 结构化类型列表
  • Views - 连接字符串中指定的数据库的视图列表
  • ViewColumns - 连接字符串中指定的数据库的视图中的列列表
  • ProcedureParameters - 连接字符串中指定的数据库的存储过程的参数列表
  • Procedures - 连接字符串中指定的数据库的存储过程列表
  • ForiegnKeys - 连接字符串中指定的数据库的外键关系数据
  • IndexColumns - 连接字符串中指定的数据库的索引及其列列表
  • Indexes - 连接字符串中指定的数据库的索引列表
  • UserDefinedTypes - 连接字符串中指定的数据库的用户定义类型列表
JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                         "CookieStore", true, "", "",
                                         10, 20, 3, 10, "MyProgram",
                                         "MyComputer", 20161, true);
DataTable retVal = dac.GetSchemaAsync(SchemaTypesEnum.AllColumns).Result;
dac.Dispose();
dac = null;

理解SchemaFactory对象

SchemaFactory对象用于创建和填充包含模式数据的强类型对象。还有一些其他方法可能非常有用。

方法及代码示例

  • async Task<String> ConvertTableToCSClassAsync (DataTable dt, String namespaceName, String className)

    接受一个DataTable并将其创建为string格式的数据对象C#类。该类被标记为可序列化并用作数据对象。您指定类所在的命名空间以及.cs类的名称。该方法返回一个String,可以写入文件作为C#类。此函数的一个用途是,当使用此库执行SQL时,您可以获取SQL查询返回的DataTable,将其用于此方法,现在您就有了一个C#类,已完全编码并准备好编译。此方法用于创建此库中使用的模式类的代码。

    // Code Example:
    // retVal is a DataTable object you have obtained elsewhere
    String targetClassFileName = Environment.CurrentDirectory + 
                                 @"\" + schemaType.ToString() + "DO.cs";
    SchemaFactory fac = new SchemaFactory();
    String csClass = fac.ConvertTableToCSClassAsync(retVal,
                                                    "MyNamespace.Something",
                                                    schemaType.ToString() + "DO").Result;
    System.IO.File.WriteAllText(targetClassFileName, csClass);
    fac = null;
  • async Task<String> GetFactoryMethodSchemaCodeAsync(DataTable dt, SchemaTypesEnum schemaType, String altDOName = "Test")

    创建用于填充DO类的异步方法的代码,使用作为参数传入的JDataAccessSQL数据访问组件。该方法特定于由ConvertTableToCSClass()创建的DO,使用传入的schemaTypeDataTable。该方法返回一个包含完整C#方法代码的string。此方法的一个使用示例是创建创建模式相应类所需的代码。此方法用于生成此库中部分代码。

    // Code Example:
    // retVal is a DataTable object you have obtained elsewhere
    String targetClassFileName = Environment.CurrentDirectory +
                                 @"\SchemaFactoryMethod.cs";
    SchemaFactory fac = new SchemaFactory();
    SchemaTypesEnum schemaType = <one of the SchemaTypesEnum enum values other than Undefined>
    String factoryMethodString = 
              fac.GetFactoryMethodSchemaCodeAsync(retVal, schemaType).Result;
    System.IO.File.AppendAllText(targetClassFileName, factoryMethodString);
    fac = null;
  • async Task<String> GetFactoryMethodCodeAsync(DataTable dt, String dOName)

    此方法接受一个DataTable对象,并创建用于填充类实例(类名由String参数dOName表示)的方法的C#代码。属性**必须**与DataTable中的列名具有相同的名称和区分大小写的拼写。如果您使用了此SchemaFactory对象中的方法“ConvertTableToCSClassAsync”,那么这部分将得到处理。请注意,由名称dOName表示的类是一行数据,而不是一个集合。

    //Code Example:
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    DBReturnValue retVal = dac.ExecuteQueryAsync("SELECT * FROM Cookies", false, null).Result;
    DataTable retTable = retVal.Data.Tables[0];
    SchemaFactory sf = new SchemaFactory();
    // This gets the C# code for the class representing the table data,
    // in this example called CookieDO..
    String tempCSFile = sf.ConvertTableToCSClassAsync
                        (retTable, "YourNamespace.Cookies", "CookieDO").Result;
    // This gets the C# code to populate one instance of the class (the code created above)
    // and return 1 to n instances in a List<T> object. In this example, it would be
    // a List<CookieDO> object.
    String tempMethod = sf.GetFactoryMethodCodeAsync(retTable, "CookieDO").Result;
    sf = null;
    dac.Dispose();
    dac = null;

    现在,您可以让此库从查询的DataTable实例生成C#类文件和填充它的方法。

  • async Task<String> GetDataTableContentsAsDelimitedFileAsync(DataTable dataTable, String fieldDelimiter)

    接受一个DataTable并使用指定的字段分隔符从数据创建用于分隔文件的string。调用者必须决定使用什么作为分隔符,以便数据中不使用该分隔符。建议使用值[((Char)28).ToString()]

    // Code Example:
    // retVal is a DataTable object you have obtained elsewhere
    SchemaFactory fac = new SchemaFactory();
    String schema = fac.GetDataTableContentsAsDelimitedFileAsync(retVal,
                                                                ((Char)28).ToString()).Result;
    fac = null;
  • async Task<String> GetDataTableSchemaAsDelimitedFileAsync(DataTable dataTable, String fieldDelimiter)

    接受一个DataTable并使用指定的字段分隔符从模式创建分隔文件。调用者必须决定使用什么作为分隔符,以便数据中不使用该分隔符。建议使用值[((Char)28).ToString()]。该方法返回一个包含分隔文件的String

    // Code Example:
    // retVal is a DataTable object you have obtained elsewhere
    SchemaFactory fac = new SchemaFactory();
    String schema = fac.GetDataTableSchemaAsDelimitedFileAsync(retVal,
                                                              ((Char)28).ToString()).Result;
    fac = null;

    以下方法返回模式对象,其中包含对应于SchemaTypesEnum枚举的特定模式集合的信息。此方法创建并填充一个对象实例,其中包含匹配返回对象的模式类型查询的数据。

    *** 创建的代码需要NuGet包 System.Data.DataExtensions。 ***

    这是一个典型的代码示例。您可以将其应用于任何方法。

    // Code Example:
    // retVal is a DataTable object you have obtained elsewhere
    JDataAccessSQL dac = new JDataAccessSQL(@"SQLServerABC\SomeInstance",
                                             "CookieStore", true, "", "",
                                             10, 20, 3, 10, "MyProgram",
                                             "MyComputer", 20161, true);
    SchemaFactory fac = new SchemaFactory();
    List<AllColumnsDO> returnValue = fac.GetAllColumnsDO(dac).Result;
    fac = null;

类似方法

  • async Task<List<AllColumnsDO>> GetAllColumnsDO(JDataAccessSQL dac)
  • async Task<List<ColumnsDO>> GetColumnsDO(JDataAccessSQL dac)
  • async Task<List<ColumnSetColumnsDO>> GetColumnSetColumnsDO(JDataAccessSQL dac)
  • async Task<List<DatabasesDO>> GetDatabasesDO(JDataAccessSQL dac)
  • async Task<List<DataSourceInformationDO>> GetDataSourceInformationDO(JDataAccessSQL dac)
  • async Task<List<DataTypesDO>> GetDataTypesDO(JDataAccessSQL dac)
  • async Task<List<ForiegnKeysDO>> GetForiegnKeysDO(JDataAccessSQL dac)
  • async Task<List<IndexColumnsDO>> GetIndexColumnsDO(JDataAccessSQL dac)
  • async Task<List<IndexesDO>> GetIndexesDO(JDataAccessSQL dac)
  • async Task<List<MetaDataCollectionsDO>> GetMetaDataCollectionsDO(JDataAccessSQL dac)
  • async Task<List<ProcedureParametersDO>> GetProcedureParametersDO(JDataAccessSQL dac)
  • async Task<List<ProceduresDO>> GetProceduresDO(JDataAccessSQL dac)
  • async Task<List<ReservedWordsDO>> GetReservedWordsDO(JDataAccessSQL dac)
  • async Task<List<StructuredTypeMembersDO>> GetStructuredTypeMembersDO(JDataAccessSQL dac)
  • async Task<List<TablesDO>> GetTablesDO(JDataAccessSQL dac)
  • async Task<List<UserDefinedTypesDO>> GetUserDefinedTypesDO(JDataAccessSQL dac)
  • async Task<List<UsersDO>> GetUsersDO(JDataAccessSQL dac)
  • async Task<List<ViewColumnsDO>> GetViewColumnsDO(JDataAccessSQL dac)
  • async Task<List<ViewsDO>> GetViewsDO(JDataAccessSQL dac)

历史

作者 什么
07/26/2019 JDJ Genesis
© . All rights reserved.