我之前已经问过这个问题,但是在那些问题中没有足够详细的实际实现,所以我决定搜索一些关于如何实现这个问题的信息,这就是我&#39到目前为止:
IUnitOfWork界面:
public interface IUnitOfWork : IDisposable
{
IDomainTableRepository DomainTables { get; }
IVariableRepository Variables { get; }
IModelRepository Models { get; }
IStructureRepository Structures { get; }
ISentenceRepository Sentences { get; }
IExpressionRepository Expressions { get; }
IReturnRepository Returns { get; }
void Commit();
}
IUnitOfWork的实施:
public class SqlUnitOfWork : IUnitOfWork
{
const string ConnectionStringName = "DefaultConnection";
private AdoNetContext _context;
private DomainTableRepository _domainTables;
private VariableRepository _variables;
private ModelRepository _models;
private StructureRepository _structures;
private SentenceRepository _sentences;
private ExpressionRepository _expressions;
private ReturnRepository _returns;
public SqlUnitOfWork()
{
var connectionString =
ConfigurationManager
.ConnectionStrings[ConnectionStringName]
.ConnectionString;
_context = new AdoNetContext(connectionString, true);
}
public IDomainTableRepository DomainTables
{
get
{
if (_domainTables == null)
{
_domainTables = new DomainTableRepository(_context);
}
return _domainTables;
}
}
//...getters for the remaining repositories
public void Commit()
{
_context.SaveChanges();
}
#region IDisposable Support
private bool disposedValue = false;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_context.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
AdoNetContext类
本课程实施的所有功劳归于@jgauffin。
His original blog post can be found here.
public class AdoNetContext : IDisposable
{
private IDbConnection _connection;
private bool _ownsConnection;
private IDbTransaction _transaction;
public AdoNetContext(string connectionString, bool ownsConnection)
{
_connection = new SqlConnection(connectionString);
_connection.Open();
_ownsConnection = ownsConnection;
_transaction = _connection.BeginTransaction();
}
public IDbCommand CreateCommand()
{
var command = _connection.CreateCommand();
command.Transaction = _transaction;
return command;
}
public void SaveChanges()
{
if (_transaction == null)
{
throw new InvalidOperationException("Transaction have already been already been commited. Check your transaction handling.");
}
_transaction.Commit();
_transaction = null;
}
public void Dispose()
{
if (_transaction != null)
{
_transaction.Rollback();
_transaction = null;
}
if (_connection != null && _ownsConnection)
{
_connection.Close();
_connection = null;
}
}
}
使用AdoNetContext的存储库(DomainTableRepository)的实现:
public class DomainTableRepository : IDomainTableRepository
{
private AdoNetContext _context;
public DomainTableRepository(AdoNetContext context)
{
_context = context;
}
public DomainTable Get(int id)
{
DomainTable table;
using (var commandTable = _context.CreateCommand())
{
commandTable.CommandType = CommandType.StoredProcedure;
commandTable.CommandText = "up_DomainTable_GetById";
commandTable.Parameters.Add(commandTable.CreateParameter("@pId", id));
table = ToList(commandTable).FirstOrDefault();
}
return table;
}
public IEnumerable<DomainTable> GetAll(int pageIndex = 1, int pageSize = 10)
{
using (var command = _context.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "up_DomainTable_GetAll";
command.Parameters.Add(command.CreateParameter("@pPageIndex", pageIndex));
command.Parameters.Add(command.CreateParameter("@pPageSize", pageSize));
return ToList(command).ToList();
}
}
public int Remove(DomainTable entity)
{
using (var command = _context.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "up_DomainTable_Delete";
command.Parameters.Add(command.CreateParameter("@pId", entity.Id));
return command.ExecuteNonQuery();
}
}
}
我为张贴这么多代码而道歉,但我想确保你理解我想要问的一切。
首先,我为UoW(IUnitOfWork)创建了一个界面,因为将来我可能想要改成像EF这样的ORM,但是因为我只是迈出了我的第一步 - 结束编程我想从ADO.NET和存储过程开始。
以下是关于使用ADO.NET实现UoW模式及其在ASP.NET MVC中的用法的问题:
1)鉴于 AdoNetContext (管理数据库连接和事务的代码)的代码,总是创建一个事务是否有任何性能损失?
这是我在SQL书中读到的:&#34;执行SELECT 事务中的语句可以在引用的表上创建锁定,这可以阻止其他用户或会话执行工作或读取数据&#34; 在C#中创建的事务是否与SQL中的对应事务完全相同?
2)正如您在IUnitOfWork及其实现(UnitOfWork)中所看到的,我在应用程序中拥有每个存储库的只读属性。这是一个常见的&#34;模式&#34;我已经在很多关于EF的教程中看到过,我发现它非常方便,因为每次我创建一个IUnitOfWork实例时,我都可以访问它的所有存储库,而且我不必将我的代码弄乱我的代码。我需要在特定Action
(来自Controller
)中实例化我需要的存储库。
您是否认为每次创建/注入新的IUnitOfWork实例时,实例化所有存储库(如SQLUnitOfWork所做的那样)会花费太多开销?在某些情况下我可能会使用它同时有4个或5个存储库,但在大多数情况下,我只会在同一个action
中使用1个或2个。
3)我想使用DI(可能是Ninject)将IUnitOfWork的实例注入到我的Controller
中。这种方式稍后当我使用另一个持久性框架时,我只需要更改此行kernel.Bind<IUnitOfWork>().To<SqlUnitOfWork>();
来自SqlUnitOfWork
,让我们说EFUnitOfWork
。
我在这里遇到的问题是,Dispose
和SqlUnitOfWork
中的AdoNetContext
方法从未被调用过,而且我想要使用DI I&#39; d而是将SqlUnitOfWork
的实例化包装在每个using
的{{1}}语句中,而不是泄漏内存,以便我可以使用DI。
所以这就是我想问你们的人。
我在尝试学习之前请先点击关闭链接或将问题标记为重复,请花些时间阅读我的问题。
感谢。