分层开发利于模块之间的解耦,一般常见的三层方式:UI层\业务逻辑层\数据访问层
这有个问题想和大家讨论学习,请高手们不吝指教:当软件有较复杂的业务需求时,可以在数据库中编写存储过程,一个存储过程中去执行多个SQL语句.
但由于分层的需求,往往也可以在业务层编写方法去逐一调用数据访问层的多个方法
但如果需要事务处理时,就出现了问题,在数据库中编写存储过程来执行事务处理.这样做的话,业务逻辑层的存在就没有了价值,瘦业务逻辑层也使数据库服务器增大了负担,应用服务器仅仅成为了UI层的平台.
如果要把事务处理放到业务层的话,本人还不知道如何实现,DbTranscation的实例化是需要一个DbConnection对象的,按分层开发的解耦原则来说,这个不可行.如果把事务处理放置到数据访问层去做的话,与直接写事务的存储过程没有区别,另外,同样也造成了瘦业务逻辑层.其他,一句话综述:
为均衡数据库服务器与应用程序服务器,并且集中软件中的逻辑处理到业务层,如何在业务层进行事务处理.当然,如果在数据层实现事务\或都在数据库编写事务存储过程,是否也合理,请有高见的谈谈.还有一点,我思索的:很多程序喜欢用SqlHelper的方式去访问处理数据层,但有些数据层在创建Connection时,习惯为每一个数据库操作创建一个Connection,并且使用完后,立即关闭和释放Connection.这种方法是不可能提供给业务层事务处理的基础的..Net事务处理的基础就是在同一个Connection上执行多个数据库操作时,才能实现Commit或Rollback的.话题比较大,讨论的重点还是在业务逻辑层实现事务处理?或是数据层实现事务?或是存储过程实现事务?若应该在业务逻辑层实现事务处理,应该如何完成?
这有个问题想和大家讨论学习,请高手们不吝指教:当软件有较复杂的业务需求时,可以在数据库中编写存储过程,一个存储过程中去执行多个SQL语句.
但由于分层的需求,往往也可以在业务层编写方法去逐一调用数据访问层的多个方法
但如果需要事务处理时,就出现了问题,在数据库中编写存储过程来执行事务处理.这样做的话,业务逻辑层的存在就没有了价值,瘦业务逻辑层也使数据库服务器增大了负担,应用服务器仅仅成为了UI层的平台.
如果要把事务处理放到业务层的话,本人还不知道如何实现,DbTranscation的实例化是需要一个DbConnection对象的,按分层开发的解耦原则来说,这个不可行.如果把事务处理放置到数据访问层去做的话,与直接写事务的存储过程没有区别,另外,同样也造成了瘦业务逻辑层.其他,一句话综述:
为均衡数据库服务器与应用程序服务器,并且集中软件中的逻辑处理到业务层,如何在业务层进行事务处理.当然,如果在数据层实现事务\或都在数据库编写事务存储过程,是否也合理,请有高见的谈谈.还有一点,我思索的:很多程序喜欢用SqlHelper的方式去访问处理数据层,但有些数据层在创建Connection时,习惯为每一个数据库操作创建一个Connection,并且使用完后,立即关闭和释放Connection.这种方法是不可能提供给业务层事务处理的基础的..Net事务处理的基础就是在同一个Connection上执行多个数据库操作时,才能实现Commit或Rollback的.话题比较大,讨论的重点还是在业务逻辑层实现事务处理?或是数据层实现事务?或是存储过程实现事务?若应该在业务逻辑层实现事务处理,应该如何完成?
但是BLL中还真得引用System.Data.SqlClient了?
这BLL还是BLL么?
请高手有想法的指点指点
像这类话我在csdn或者其它论坛看过不少,但我始终没有看懂。不知道这是来自于哪一条“解耦原则”,甚至不知道那种所谓“解耦”的目的到底是要解决什么“耦合”。如果从最终交互界面设计需求实际出发,什么地方是内聚的什么地方是耦合的其边界很清楚,本来就是高内聚的地方也不会打折解耦的旗号去花精力想办法拆散它。
的确是个好问题。我也碰到过类似的问题。但是被我用别的办法绕开了。
如何绕开???求解
第一种情况:
Using(sqlconnection connection = new sqlconnection(strConnectString))
{
sqlTransaction transation = connection.BeginTransation;
然后把transaction传入数据层进行数据访问,一旦抛出异常就调用transaction.rollBack();
}第二种情况:
如果逻辑层中还需要调用多个诸如上面第一种情况这样的已经有了sqlTransaction处理的逻辑层方法,
那么就要使用TransactionScope(分布式事物,需要配置MTC) 在调用以上的逻辑层方法时,一旦有
一个SqlTransaction出现异常,那么所有的sqlTransaction都会被回滚!不知道能否满足你的解耦!
---------------------
.NET没有类似Java里的JTA之类的事务管理器吗?怎么会有人在这个总是上想解决办法呢?好奇怪啊。
居然有人说是个好问题。
并不是说一个存储过程就一定是一个事物吧!那只是一堆sql语句而已。
事物的控制还是可以放在业务逻辑层啊!
比如:开始事物:
调用sqlA
调用存储过程(相当于sqlB),一般来说框架都会对存储过程的调用封装的,和调用sql应该没有本质区别。
调用sqlC
提交或回滚事物
导航到不同的Uer view层。强调一下:导航层不进行任何的业务逻辑计算,只是判断请求操作成功与否做出相应的导航操作。2.业务逻辑模块层(一般由CXXService或 CXXManager类模块组成),主要职责执行业务逻辑的计算,业务逻辑可以很简单,简单到只是简单的调用CXXXDAO的一个save操作。也可以很复杂,复杂到要用到多个CXXXDAO(或者说是多个table表)才能完成。即使用到了多个table表,业务逻辑层也不应该直接用sql操作table表,那样会带来维护的复杂度,这时应该新建一个能操作相关table的CXXXDAO新类,让这个新类来完成业务逻辑要求的复杂的sql(或是复杂的存储过程)。------(建议复杂问题尽量简单化)。3.DAO层(即数据访问层)。主要职责完成各种各样的存储、查询操作。主要作用是 向上提供不同的存储接口及查询。如saveUserAndXxx();getUserAdnXxx()等等;以求对数据访问的简单化。提供数据的简化访问的同时也屏蔽了数据库的存在,业务逻辑层不需要知道DAO层到底在用那个数据库,或者根本就没用。这是我对UI层\业务逻辑层\数据访问层的理解,同时也说到了大家容易忽略的viewCntrl导航层,虽然这一层操作少,但我是还认为它应该算一层。好了,说了那么多希望对你能有点用处。不要你分!哈哈哈!
(1)Business Function 子层负责基本业务功能的实现。
(2)Business Flow 子层负责将Business Function子层提供的多个基本业务功能组织成一个完整的业务流。(Transaction只能在Business Flow 子层开启。)原帖请看这里:
http://www.cnblogs.com/morningwang/archive/2008/04/14/1153518.html
用存储过程,最直接解决了事务的问题。
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;namespace SVNGo.DAL
{
public class DBContext
{
private Database _db = null;
private DbTransaction _transaction = null;
private DbConnection _conn = null;
private int _transactionRef = 0; public static DBContext CreateDBContext(string connName)
{
return new DBContext(connName);
} public DBContext(string connName)
{
_db = DatabaseFactory.CreateDatabase(connName);
} public void BeginTransaction(IsolationLevel isolevel)
{
if (_transaction != null && _transactionRef > 0)
{
++_transactionRef;
}
else
{
_conn = _db.CreateConnection();
_conn.Open();
_transaction = _conn.BeginTransaction(isolevel);
++_transactionRef;
}
} public void Commit()
{
if (_transaction != null && _transactionRef > 0)
{
--_transactionRef;
if (_transactionRef == 0)
{
_transaction.Commit();
_transaction = null;
if (_conn != null && _conn.State == ConnectionState.Open)
{
_conn.Close();
_conn = null;
}
}
}
} public void Rollback()
{
if (_transaction != null && _transactionRef > 0)
{
_transaction.Rollback();
_transactionRef = 0;
_transaction = null; if (_conn != null && _conn.State == ConnectionState.Open)
{
_conn.Close();
_conn = null;
}
}
} public DbCommand GetStoredProcCommand(string storedProcedureName)
{
return _db.GetStoredProcCommand(storedProcedureName);
} public void DiscoverParameters(DbCommand dc)
{
_db.DiscoverParameters(dc);
} public int ExecuteNonQuery(DbCommand dc)
{
if (_transaction != null)
{
return _db.ExecuteNonQuery(dc, _transaction);
}
else
{
return _db.ExecuteNonQuery(dc);
}
} public DbDataReader ExecuteReader(DbCommand dc)
{
DbDataReader dr = null;
DataReaderWrapper drw = _db.ExecuteReader(dc) as DataReaderWrapper;
if (drw != null)
{
dr = drw.InnerReader as DbDataReader;
} return dr;
}
}
}
_dbContext = new DBContext(svnlib);
_changeDAL = new ***DAL(_dbContext); try
{
_dbContext.BeginTransaction(IsolationLevel.ReadUncommitted);
业务逻辑 _dbContext.Commit(); }
catch (***Exception)
{
_dbContext.Rollback();
throw;
}
catch (Exception e)
{
_dbContext.Rollback(); }