5ifree.eicp.net

瑞雪年

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  221 随笔 :: 0 文章 :: 358 评论 :: 0 引用

不好意思,借首页作个广告,给大家介绍个开源的数据访问组件Data Access Component,项目网站:http://dac.codeplex.com .

项目描述:


数据访问组件,提供了一组类库和一个代码生成工具,使.net项目中数据访问更简化.

功能:

  • 多种数据库支持.
  • 提供DataSet, DataTable 和数据实体查询.
  • 执行SQL脚本及存储过程.
  • 条件表达式.
  • 常用SQL方法, 如MAX, MIN等可能被应用在查询中.
  • 数据实体代码及XML文件生成.

使用:

基本功能:

1. 使用 "EntitiesGenerator" 生成工具生成实体项目。
  参见 blog: How to use the "Enties Generator" tool to create an entities project.

2. 添加一个文件名为"connection.config"的数据库连接配置文件,到应用程序的运行目录,文件格式及内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<connections>
<connection databaseType="SQL">Data Source=.\SQLEXPRESS;AttachDbFilename="|DataDirectory|Database1.mdf";
Integrated Security=True;User Instance=True</connection>
</connections>

3. 假定我们有个实体类,名叫 "Issue", 可以使用以下代码将它插入数据库
	RaisingStudio.Data.Providers.DataContext dc = new RaisingStudio.Data.Providers.DataContext();
dc.Insert<Issue>(issue);

4. 更新实体.
	dc.Update<Issue>(issue);

5. 删除实体, 可以通过给定实体或实体的主键值进行。
	dc.Delete<Issue>(issue);

	dc.Delete<Issue>(issueID);

6. 查询实体, 通过三个不同的方法,可以分别获得 IEnumerable<T>, IList<T> or DataTable 作为返回结果。
	IEnumerable<Issue> query = dc.Query<Issue>();
foreach(Issue issue in query)
{
}
	IList<Issue> issueList = dc.QueryForList<Issue>();
在查询中,还可以使用“条件表达式”.
	DataTable dataTable = dc.QueryForDataTable<Issue>(Issue._.IssueID > 1);

7. 可以通过GetData()方法,查询单个实体,使用包含主键值的实体,主键值或条件表达式作为参数。
	Issue issue = new Issue();
issue.IssueID = 2;
issue = dc.GetData<Issue>(issue);
	Issue issue = dc.GetData<Issue>(2);
	Issue issue = dc.GetData<Issue>(Issue._.IssueID == 2);

8. 更新DataTable.
	int result = dc.UpdateDataTable<Issue>(dataTable);

高级特性:

1. 常用SQL方法, 包括 GetCount, GetMin, GetMax, GetSum and GetAvg.
int result = dc.GetCount<Issue>();
object minValue = dc.GetMin<Issue>(Issue._.Progress);
decimal maxValue = Convert.ToDecimal(dc.GetMax<Issue>(Issue._.Progress,
Issue._.Title == "test title"));

2. Save 和 Exists.
int result = dc.Save<Issue>(issue);
bool saved = dc.Exists<Issue>(issue);
bool ex = dc.Exists<Issue>(Issue._.Title == "test title");

3. 部分列.
Issue issue = dc.GetData<issue>(2, Issue._.Status);
issue.Status = IssueStatus.Fixed;
int result = dc.Update<Issue>(issue, Issue._.Status);

4. 批量操作.
int result = dc.Delete<issue>(Issue._.Status == IssueStatus.Fixed);
result = dc.Update<Issue>(issue, Issue._.Status == IssueStatus.Fixed, Issue._.Status);

5. 排序, 使用 "OrderBy" 方法或  ^ 和  ^ ! 运算符应用在查询中,可以对查询进行排序.
IEnumerable<Issue> query = dc.Query<Issue>(Issue.All.OrderBy(Issue._.IssueID));
query = dc.Query<Issue>(Issue._.Status == IssueStatus.Fixed ^ Issue._.IssueID);

6. 分页.
 IList<Issue> issueList = dc.QueryForList<Issue>(Issue.All, 0, 100);

7. 事务.
try
{
this.dc.BeginTransaction();
try
{
int result = this.dc.Insert<Issue>(issue);
this.dc.CommitTransaction();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
this.dc.RollbackTransaction();
throw;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
throw;
}

8. 多主键.
MutipleKeysTable mt = dc.GetData<MutipleKeysTable>(new object[] { key1, key2 }, 
MutipleKeysTable.Except(MutipleKeysTable._.Value2));

9. 使用 common command 查询.
CommonCommand cmd = new CommonCommand();
cmd.CommandText = string.Format("SELECT [IssueID], [{0}] FROM .[Issue] WHERE [{0}] = @p1", Issue._.Title);
cmd.Parameters.Add("@p1", "test title");
Issue issue = dc.GetData<Issue>(cmd);

10. 执行 common command, 支持 ExecuteForDataTable, ExecuteForList, ExecuteQuery, ExecuteReader, ExecuteScalar 和 ExecuteNoQuery 等方法.
RaisingStudio.Data.CommonCommand cmd = new CommonCommand(
string.Format("UPDATE .[{0}] SET [{1}] = [{1}] + 1 WHERE [{2}] = @p1",
Issue._, Issue._.Progress, Issue._.IssueID));
cmd.AddParameter("@p1", System.Data.DbType.Int32, maxID);
int result = this.dc.ExecuteNoQuery<Issue>(cmd);

11. SQL 脚本日志.
DataContext dc = new DataContext();
dc.Log = System.Console.Out;

12. 多种数据库 providers, 添加如下的 xml 项到 "providers.config" 配置文件中, 就可以在 "connections.config" 中使用.
    <provider 
name="MYSQL"
description="MySQL, MySQL provider "
enabled="false"
assemblyName="MySql.Data, Version=5.2.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"
connectionClass="MySql.Data.MySqlClient.MySqlConnection"
commandClass="MySql.Data.MySqlClient.MySqlCommand"
parameterClass="MySql.Data.MySqlClient.MySqlParameter"
parameterDbTypeClass="MySql.Data.MySqlClient.MySqlDbType"
parameterDbTypeProperty="MySqlDbType"
dataAdapterClass="MySql.Data.MySqlClient.MySqlDataAdapter"
commandBuilderClass="MySql.Data.MySqlClient.MySqlCommandBuilder"
usePositionalParameters="false"
useParameterPrefixInSql="true"
useParameterPrefixInParameter="true"
parameterPrefix="?"
allowMARS="false"
/>

13. 自定义数据类型“转换器”,  以下就是一个 "TypeConverter" 示例代码,及如何配置到 "converters.config" 配置文件中.
public class PointConverter : IDbTypeConverter
{
#region IDbTypeConvertermember
public object ConvertFromDbType(object value)
{
string s = value as string;
if (!string.IsNullOrEmpty(s))
{
string[] sa = s.Split(',');
if ((sa != null) && (sa.Length == 3))
{
int x = int.Parse(sa[0]);
int y = int.Parse(sa[1]);
int z = int.Parse(sa[2]);
return new Point(x, y, z);
}
}
return null;
}
public object ConvertToDbType(object value)
{
if (value is Point)
{
Point point = (Point)value;
return point.ToString();
}
return null;
}
#endregion
}
    <converter type="RaisingStudio.Data.Entities.Point, 
RaisingStudio.Data.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
dbType="string"
converterType="RaisingStudio.Data.Entities.PointConverter,
RaisingStudio.Data.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
</converter>

14. “实体定义”配置, "*.definition.xml" 文件可以作为资源文件嵌入到程序集在,也可以留在文件系统上,"EntitiesGenerator" 实体生成工具生在项目是采用的嵌入资源的方式, 如果要使用文件的方式,则需要配置一个名叫"definitions.config"的配置文件,样式如下:
<?xml version="1.0" encoding="utf-8"?>
<definitionsConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<aliases>
<alias name="UTIssue" type="UnitTest.UTIssue, UnitTest, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null" />
</aliases>
<definitions>
<definition name="UTIssue" resource="definitions/Issue.definition.xml" />
<definition name="UTSystemUser" resource="definitions/SystemUser.definition.xml" />
</definitions>
</definitionsConfig>


15. Common command 管理器. 把 SQL脚本配置在 "commands.config" 中后,可以用如下代码读取使用。
<?xml version="1.0" encoding="utf-8" ?>
<commands parameterPrefix=":">
<command name="select">SELECT * FROM DAC_ISSUE</command>
<command name="select2">
<![CDATA[
SELECT * FROM DAC_USER
]]>
</command>
<command name="select3" commandType="StoredProcedure">SELECT_DAC_ISSUE</command>
<command name="select4">
<![CDATA[
SELECT * FROM DAC_ISSUE DI
WHERE DI.ISSUE_ID = :ISSUE_ID
]]>
</command>
</commands>
CommonCommand cmd = CommandManager.Instance.GetCommand("select");
System.Data.DataTable dt = this.dc.ExecuteForDataTable(cmd);

posted on 2009-04-07 21:01 瑞雪年 阅读(3455) 评论(22) 编辑 收藏

评论

类似的太多了
 回复 引用   

每个人都有自己的习惯,除了微软,好像谁都统一不了,不对,微软也没有做到。

所以,现在还是自己用着自己习惯的方式来操作数据。

你的方法给我的感觉就是太死板了,侵入性太强,呵呵。

 回复 引用 查看   

你给的连接怎么是英文的呢?你的这个方法不是你自己写的吗?
 回复 引用 查看   

#4楼 2009-04-08 00:33 gkjkjl[未注册用户]
看起来比企业库的数据访问还牛
 回复 引用   

#5楼 2009-04-08 07:52 Dominic[未注册用户]
还不如用LINQTOSQL
 回复 引用   

#6楼 2009-04-08 08:11 aierong      
开源就是好

佩服lz
 回复 引用 查看   

#7楼[楼主] 2009-04-08 08:50 瑞雪年      
--引用--------------------------------------------------
金色海洋(jyk): 你给的连接怎么是英文的呢?你的这个方法不是你自己写的吗?

--------------------------------------------------------
是我写的,最早发布在codeplex上。
 回复 引用 查看   

#8楼 2009-04-08 09:24 yunhuasheng      
楼主善于总结,赞一个先。
 回复 引用 查看   

#9楼 2009-04-08 10:37 哎[未注册用户]
我linq都不要,还要这个干嘛,类似的太多了,泛滥
 回复 引用   

#10楼 2009-04-08 11:18 沧海一声笑
都自己写自己的啦 呵呵 方便简单!
 回复 引用   

#11楼 2009-04-08 11:49 dicky      
呼呼,好哇, 开源了..
*多种数据库支持. :) 喜欢这个..
下载瞧瞧..
 回复 引用 查看   

#12楼 2009-04-08 14:22 代码乱了      
--引用--------------------------------------------------
金色海洋(jyk): 每个人都有自己的习惯,除了微软,好像谁都统一不了,不对,微软也没有做到。

所以,现在还是自己用着自己习惯的方式来操作数据。

你的方法给我的感觉就是太死板了,侵入性太强,呵呵。


--------------------------------------------------------
死板?我倒不觉得,操作习惯和其他的ORM操作类似,侵入性这个问题不好说
 回复 引用 查看   

写的很好!

请问 如何得到刚刚产生的自增长主键?
尤其在事物处理中,这个尤其重要。
 回复 引用   

#14楼[楼主] 2009-04-08 21:04 瑞雪年      
--引用--------------------------------------------------
未登录的王亮: 写的很好!

请问 如何得到刚刚产生的自增长主键?
尤其在事物处理中,这个尤其重要。

--------------------------------------------------------
这个还需要一个操作,GetMax(), 如下:
this.dc.Insert<Issue>(issue);
this.issueList.Add(Convert.ToInt32(this.dc.GetMax<Issue>(Issue._.IssueID)));
 回复 引用 查看   

呵呵,这个方案并发起来问题很多哦,还有其他方案吗?
 回复 引用   

CommandBuilder.cs 是否来自Ibatis.Net ?

in line 422
public System.Data.IDbCommand GetInsertCommand(System.Data.Common.DataTableMapping dataTableMapping, bool getAutoIncrementValue)

如果 getAutoIncrementValue is true 生成的sql 如下
INSERT INTO DAC_ISSUE (ISSUE_TITLE, ISSUE_DESC, ISSUE_STS, ISSUE_TYP, ISSUE_OWNR, ISSUE_PRGS, CREATE_TM, ISSUE_LOCKED) VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8); SELECT ISSUE_ID FROM DAC_ISSUE WHERE (ISSUE_ID = SCOPE_IDENTITY())

看来 原始代码考虑比较周密了,呵呵。
 回复 引用   

#17楼[楼主] 2009-04-08 21:45 瑞雪年      
--引用--------------------------------------------------
未登录的王亮: 呵呵,这个方案并发起来问题很多哦,还有其他方案吗?

--------------------------------------------------------
本想设计成同时生成两条SQL语句,一起执行,可是在有的数据库上不支持,后来就取消了,其实把Insert和GetMax放在一个事务中,应该不会有并发问题呀?!
 回复 引用 查看   

#18楼[楼主] 2009-04-08 21:50 瑞雪年      
--引用--------------------------------------------------
未登录的王亮: CommandBuilder.cs 是否来自Ibatis.Net ?

in line 422
public System.Data.IDbCommand GetInsertCommand(System.Data.Common.DataTableMapping dataTableMapping, bool getAutoIncrementValue)

如果 getAutoIncrementValue is true 生成的sql 如下
INSERT INTO DAC_ISSUE (ISSUE_TITLE, ISSUE_DESC, ISSUE_STS, ISSUE_TYP, ISSUE_OWNR, ISSUE_PRGS, CREATE_TM, ISSUE_LOCKED) VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8); SELECT ISSUE_ID FROM DAC_ISSUE WHERE (ISSUE_ID = SCOPE_IDENTITY())

看来 原始代码考虑比较周密了,呵呵。
--------------------------------------------------------

对,就是这样的,在SQL Server中好用,可别的数据库就不一定好用了。
 回复 引用 查看   

#19楼[楼主] 2009-04-08 21:54 瑞雪年      
在IBatis.net没注意到有command builder什么的东西,也可能是我看的不够仔细吧,但providers确实是从IBatis.net移植过来的, http://dac.codeplex.com/Thread/View.aspx?ThreadId=51079.
 回复 引用 查看   

SELECT ISSUE_ID FROM DAC_ISSUE WHERE (ISSUE_ID = SCOPE_IDENTITY())

=========================

这个好奇怪哦,是不是可以写成 SELECT ISSUE_ID= SCOPE_IDENTITY() 呢?

另外这个是不是只是针对与“自增”类型的主键才管用呢?
 回复 引用 查看   

#21楼 2009-05-07 14:51 代码乱了      
是否支持SQL Server?
 回复 引用 查看   

#22楼 2009-05-07 16:36 zhongzf[未注册用户]
--引用--------------------------------------------------
代码乱了: 是否支持SQL Server?
--------------------------------------------------------

当然支持了!并且一定要支持了!!!写个.net数据层不支持SQL Server,微软也会不乐意的!!哈哈!开个玩笑!!!
 回复 引用   

#23楼 2009-05-07 16:39 zhongzf[未注册用户]
默认支持SQL,ORACLE,ODBC和OLEDB,还可通过配置providers.config支持更多的数据库,格式可参见上面第12条。
 回复 引用