JDAC - 数据访问及更多





0/5 (0投票)
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 = "")
异步方法,根据请求的模式类型获取模式元素数据。该方法返回一个带有模式定义的
DataTable
。DataTable
列根据每个模式类型而变化。您可以使用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,使用传入的schemaType
和DataTable
。该方法返回一个包含完整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 |