【发布时间】:2021-03-26 17:04:12
【问题描述】:
我有一个带有服务类的应用程序,它从数据库中检索数据库元数据并将其返回给调用类。
要连接到数据库,服务类方法接受一个详细说明连接凭据的参数。
我正在考虑将凭据存储在服务类中的更改。造成这种情况的原因之一是调用类(例如,负责比较不同服务器上的模式)可能连接到多个不同的数据库/服务器,因此调用类基本上会有这些服务类的集合,而不是而不是连接凭据的集合(例如,以下示例中的 IConnectionInfo)。
我可能想在应用程序中做的另一件事是为不同类型的 RDBMS(例如 SQL Server、Oracle 等)实现此服务类(以下示例中为 IDatabaseService),这似乎就像让它保持开放的最佳方式(从服务返回的信息将非常通用,适用于所有受支持的 RDBMS 类型)。
服务类的示例代码:
public class DatabaseService : IDatabaseService
{
private readonly IConnectionInfo ConnectionInfo;
public bool IsConnected; // INotifyPropertyChanged
public string ServerName => IConnectionInfo.ServerName;
public string DatabaseName => IConnectionInfo.DatabaseName;
public DatabaseService(IConnectionInfo connectionInfo)
{
ConnectionInfo = connectionInfo;
}
public IEnumerable<Table> GetTables()
{
...
}
public IEnumerable<Column> GetTableColumns(Table table)
{
...
}
}
我对这种方法有点怀疑的原因有几个:
-
我正在这个类中实现
INotifyPropertyChanged,以便我可以更新 UI 以向用户显示他们是否已连接(例如,如果对服务器的任何调用失败,我可以将其切换为 false)。出于这个原因,它似乎表现得像一个 ViewModel(而不是一个服务)。 -
我不确定在服务类上具有表示其状态的属性是否是一种好习惯,例如
ConnectionInfo、IsConnected。
上面的设计看起来是可以接受的吗?
更新:进一步的思考和解释
我想我要解决的特定编程问题是,例如,我可能有一个用于 SQL Server 凭据的类和一个用于 Oracle 凭据的类,两者都是IConnectionCredentials。然后我会有几个对应的IDataService 实现,它们接受IConnectionCredentials 作为参数。问题是并非所有IDataService 的实现都可以与IConnectionCredentials 的所有实现一起工作,这对我来说似乎有缺陷,所以我认为将数据访问层和“数据访问器”对象组合到一节课。我想让IDataService 包含确定要使用哪个版本的“真实”数据访问接口的逻辑可能是可行的。例如:
public class DataService : IDataService
{
private readonly RealDataServiceFactory RealDataServiceFactory;
public IEnumerable<Table> GetTables(IConnectionCredentials connectionCredentials)
{
return RealDataServiceFactory.Create(connectionCredentials).GetTables(connectionCredentials);
}
}
public class RealDataServiceFactory
{
public IRealDataService Create(IConnectionCredentials connectionCredentials)
{
if (connectionCredentials is SqlServerConnectionCredentials)
{
return new SqlServerDataService();
}
else if ...
}
}
我想要在数据访问类中使用IsConnected 属性的另一个原因是,除了连接不工作之外,服务可能不返回数据还有其他原因,而且我没有感觉到确定属于的逻辑调用类,因此喜欢数据服务可以同时返回 null 到某个调用以及向应用程序和 UI 状态的想法,“我的连接有问题”。在上面的实现中,我也会失去这个,虽然我想这可以通过在返回之前将传入的IConnectionCredentials 上的数据服务标记为IsConnected 来实现。
【问题讨论】:
-
DatabaseService本身只是一个模型。是否使用INotifyPropertyChanged属性将其公开给视图不会影响 MVVM 设计。恕我直言,MVVM 只是一种“关注点分离”的方法,它曾经被称为三层架构……它只是旧设计模式的一个新名称。 -
@ΩmegaMan 谢谢 - 提供更多关于该类将要做什么的信息,例如,它可能有一个使用
SqlConnection连接到数据库并检索数据的方法,等等 - 它仍然会被归类为简单的模型吗? -
您在处理连接的模型(和实例)上有业务逻辑,有
SqlConnection操作/实例。该主实例将驻留在 VM 上,视图将绑定到该实例的属性以显示状态。如何拉动连接的杠杆,由您决定。但在过去的 20 年里,我已经完成了您提出的类似设计。 MVVM 纯粹主义者可能会抱怨,但只要您没有在此类上暴露给 View 的 SQL 注入场景,这才是最重要的,并且此类(模型)可以在其他地方重用。这是我的看法,我可能是错的。 -
The Spiffing Brit 会称其为“公平和平衡”。 :-)
-
@ΩmegaMan 再次感谢,这对我来说绝对有意义。作为最后一个问题:在反思这一点时,我记得我在当前的
DatabaseService上有一个方法,它接受两个ConnectionInfo参数,因此它可以进行比较。使用这种新型设计,在DatabaseService上设置一个接受另一个DatabaseService作为参数的方法是否有意义/可以接受?
标签: c# wpf design-patterns mvvm