C# 我可能挂断了数据库。我不知道在任何给定的时间有多少输入数据可能被更新。在这种情况下,我有两个主要想法,我可以在抽象类中进行插入、更新和删除抽象,并在紧接着命令.ExecuteNonQuery()之前显式打开连接的同时实现它们,也可以保持现在的状态 我想从你那里得到什么?
首先,也是最重要的,你对形势的看法。其次,指出逻辑背后的任何陷阱或您碰巧发现的任何错误编码也会非常有帮助。如果您在大量数据上循环,则为每个CRUD操作打开和关闭数据库连接将受到影响。此外,还应该使用try、catch和finally。您不能保证数据库将启动,它将导致抛出异常。我认为这可能值得研究工作单元模式 在我看来,您似乎已经在使用活动记录模式,但我发现(从关注点和依赖性分离的角度来看)您的类定义是硬编码的,依赖于oracle,这意味着使用DTO的代码也必须依赖于oracle。我并不是说如果您想切换数据库,这是一个问题,我是说,对于理解和单元测试来说,拥有一个非常解耦的系统是最佳实践 数据库不可知代码 如果您查看上面编写的所有代码,就没有提到Oracle,甚至没有提到连接或事务的概念。您有一个名为C# 我可能挂断了数据库。我不知道在任何给定的时间有多少输入数据可能被更新。在这种情况下,我有两个主要想法,我可以在抽象类中进行插入、更新和删除抽象,并在紧接着命令.ExecuteNonQuery()之前显式打开连接的同时实现它们,也可以保持现在的状态 我想从你那里得到什么?,c#,performance,database-programming,C#,Performance,Database Programming,首先,也是最重要的,你对形势的看法。其次,指出逻辑背后的任何陷阱或您碰巧发现的任何错误编码也会非常有帮助。如果您在大量数据上循环,则为每个CRUD操作打开和关闭数据库连接将受到影响。此外,还应该使用try、catch和finally。您不能保证数据库将启动,它将导致抛出异常。我认为这可能值得研究工作单元模式 在我看来,您似乎已经在使用活动记录模式,但我发现(从关注点和依赖性分离的角度来看)您的类定义是硬编码的,依赖于oracle,这意味着使用DTO的代码也必须依赖于oracle。我并不是说如果您
UnitOfWork
的抽象,它在后台管理应用程序的状态。存储库使用普通类。这类代码易于模拟和编写测试。这对于可维护性来说是巨大的
数据库特定代码
class OracleApplicationRepository:IAApplicationRepository
{
公共只读OracleDbConnection\u dbConnection;
公共OracleApplicationRepository(OracleDbConnection dbConnection)
{
_dbConnection=dbConnection;
}
IEnumerable GetAll()
{
//由你决定,观众
抛出新的NotImplementedException();
}
无效更新(应用程序应用程序)
{
//由观众决定
}
作废删除(应用程序应用程序)
{
//由观众决定
}
无效插入(应用程序应用程序)
{
使用(var命令=_dbConnection.CreateCommand())
{
//或者不管语法是什么
command.Parameters[“AuthKey”]=app.AuthKey;
command.ExecuteNonQuery();
}
}
}
OracleUnitOfWork类:IUnitOfWork
{
专用只读OracleDbConnection \dbConnection;
公共OracleUnitOfWork(字符串连接字符串)
{
_dbConnection=新的OracleDbConnection(connectionString);
}
公共IApplicationRepository应用程序
{
得到
{
//这可能是懒散加载,而不是在所有地方创建新实例
返回新的OracleApplicationRepository(_dbConnection);
}
}
公共处置
{
//关闭连接和所有事务
_dbConnection.Dispose();
}
}
我不同意这一点,但我希望你能详细说明。我认为应该有例外,因为这不是错误处理的地方,因为它的目的是相当通用的。@Aelphaeis,是的,我同意。我只是想确保在某个地方使用了异常处理。好吧,我理解IApplicationRepo,但我不理解工作单元是如何与此关联的。我退房了,但它还没有完全点击。不同的人可以同时对数据库进行更改,因此在某些情况下,我可能希望回滚某些人的更改并保留其他人的更改。此模式可以实现这一点吗?工作单元是一个任务的概念,如果您的任务是创建一个新的应用程序
,那么您可能必须在一个事务中使用多个存储库(多个插入、更新和删除),以使此更改原子化。您不会在人与人之间共享UoW,一个UnitOfWork通常是一个人执行一项任务(尽管一项任务可能执行许多数据库操作)。在正在输出的实例中放置一个IAApplicationRepo以便该实例可以自行编写是否明智?我完全明白回购协议是如何运作的。能够说ApplicationInstance.Insert()对我来说是很有意义的,这就是我发现活动记录模式有问题的地方。假设你要编写代码来拯救一个人,如果你在现实生活中告诉一个人,你不会告诉他们去拯救自己。在我看来,这个人不应该有坚持自己的责任。如果一个人有一个保存方法,它将被锁定在一种保存方法中,这本身就迫使你将其与另一个系统耦合。回顾这一点,非常感谢。你真的帮了我的忙!
public abstract class PlexxisDataTransferObjects : PlexxisDatabaseRow
{
//static methods
public static List<PlexxisDatabaseRow> GetAll();
//Constructors
public PlexxisDataTransferObjects(){ }
//Methods
public abstract bool Insert(OracleConnection Conn);
public abstract bool Update(OracleConnection Conn);
public abstract bool Delete(OracleConnection Conn);
public bool Insert()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Insert(Conn);
}
}
public bool Update()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Update(Conn);
}
}
public bool Delete()
{
using (var Conn = new OracleConnection(ConnectionString))
{
Conn.Open();
return Delete(Conn);
}
}
}
//Data Transfer Objects
public sealed class Apps : PlexxisDataTransferObjects
{
//Static Methods
public override static List<PlexxisDatabaseRow> GetAll()
{
List<PlexxisDatabaseRow> collection = new List<PlexxisDatabaseRow>();
using (var Conn = new OracleConnection(ConnectionString))
{
using (var Command = new OracleCommand("select * from APPS", Conn))
{
Conn.Open();
using (var reader = Command.ExecuteReader(CommandBehavior.CloseConnection))
while (reader.Read())
collection.Add(new Apps(reader));
}
}
return collection;
}
//Fields
public int AppId;
public string AuthKey;
public string Title;
public string Description;
public bool isClientCustomApp;
//Constructors
public Apps() : base () { }
public Apps(OracleDataReader reader) : base ()
{
if (reader["APP_ID"] != DBNull.Value)
this.AppId = Convert.ToInt32(reader["APP_ID"]);
if (reader["AUTH_KEY"] != DBNull.Value)
this.AuthKey = Convert.ToString(reader["AUTH_KEY"]);
if (reader["TITLE"] != DBNull.Value)
this.Title = Convert.ToString(reader["TITLE"]);
if (reader["DESCRIPTION"] != DBNull.Value)
this.Description = Convert.ToString(reader["DESCRIPTION"]);
if (reader["IS_CLIENT_CUSTOM_APP"] != DBNull.Value)
this.isClientCustomApp = Convert.ToBoolean(reader["IS_CLIENT_CUSTOM_APP"]);
}
//Methods
public override bool Insert(OracleConnection Conn)
{
string sql = string.Empty;
sql += "INSERT INTO APPS (APP_ID, AUTH_KEY, TITLE, DESCRIPTION, IS_CLIENT_CUSTOM_APP)";
sql += "VALUES(:appid, :authkey, :title, :description, :iscust)";
using (var Command = new OracleCommand(sql, Conn))
{
AppId = GetId();
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
Command.Parameters.Add(":authkey", OracleDbType.Varchar2).Value = AuthKey;
Command.Parameters.Add(":title", OracleDbType.Varchar2).Value = Title;
Command.Parameters.Add(":description", OracleDbType.Varchar2).Value = Description;
Command.Parameters.Add(":iscust", OracleDbType.Int32).Value = Convert.ToInt32(isClientCustomApp);
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
public override bool Update(OracleConnection Conn)
{
string sql = string.Empty;
sql += "UPDATE APPS SET ";
sql += "AUTH_KEY = :authkey, TITLE = :title, DESCRIPTION = :description, IS_CLIENT_CUSTOM_APP = :iscust ";
sql += "WHERE APP_ID = :appid";
using (var Command = new OracleCommand(sql, Conn))
{
Command.Parameters.Add(":authkey", OracleDbType.Varchar2).Value = AuthKey;
Command.Parameters.Add(":title", OracleDbType.Varchar2).Value = Title;
Command.Parameters.Add(":description", OracleDbType.Varchar2).Value = Description;
Command.Parameters.Add(":iscust", OracleDbType.Int32).Value = Convert.ToInt32(isClientCustomApp);
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
public override bool Delete(OracleConnection Conn)
{
string sql = string.Empty;
sql += "DELETE FROM APPS ";
sql += "WHERE APP_ID = :appid";
using (var Command = new OracleCommand(sql, Conn))
{
Command.Parameters.Add(":appid", OracleDbType.Int32).Value = AppId;
return Convert.ToBoolean(Command.ExecuteNonQuery());
}
}
}
class Application
{
public int ID { get; set; }
public string AuthKey { get; set; }
// and so on
}
interface IApplicationRepository
{
IEnumerable<Application> GetAll();
void Update(Application app);
void Delete(Application app);
void Insert(Application app);
}
interface IUnitOfWork : IDisposable
{
IApplicationRepository Applications { get; }
void Commit();
}
void SaveButton_Click(object sender, EventArgs e)
{
// this could be resolved by dependency injection, this would know about Oracle
using (var uow = UnitOfWorkFactory.Create())
{
uow.Applications.Insert(new Application { AuthKey = "1234" });
// you may have other repo that have work done in the same transaction / connection
uow.Commit();
}
}
class OracleApplicationRepository : IApplicationRepository
{
public readonly OracleDbConnection _dbConnection;
public OracleApplicationRepository(OracleDbConnection dbConnection)
{
_dbConnection = dbConnection;
}
IEnumerable<Application> GetAll()
{
// up to you, the viewer
throw new NotImplementedException();
}
void Update(Application app)
{
// up to the viewer
}
void Delete(Application app)
{
// up to the viewer
}
void Insert(Application app)
{
using (var command = _dbConnection.CreateCommand())
{
// or whatever the syntax is
command.Parameters["AuthKey"] = app.AuthKey;
command.ExecuteNonQuery();
}
}
}
class OracleUnitOfWork : IUnitOfWork
{
private readonly OracleDbConnection _dbConnection;
public OracleUnitOfWork(string connectionString)
{
_dbConnection = new OracleDbConnection(connectionString);
}
public IApplicationRepository Applications
{
get
{
// this could be lazy loaded instead of making new instances all over the place
return new OracleApplicationRepository(_dbConnection);
}
}
public Dispose()
{
// close the connection and any transactions
_dbConnection.Dispose();
}
}