C# 业务对象之间的关系过于易访问,且资源极度匮乏。我怎样才能解决这个问题?
首先,这似乎是一个很长的问题。我不认为是。。。代码只是我目前所做工作的概述。这感觉不对劲,所以我正在寻找建设性的批评和警告,寻找我能做什么的陷阱和建议 我有一个包含业务对象的数据库。C# 业务对象之间的关系过于易访问,且资源极度匮乏。我怎样才能解决这个问题?,c#,business-objects,data-access,C#,Business Objects,Data Access,首先,这似乎是一个很长的问题。我不认为是。。。代码只是我目前所做工作的概述。这感觉不对劲,所以我正在寻找建设性的批评和警告,寻找我能做什么的陷阱和建议 我有一个包含业务对象的数据库。 我需要访问父对象的属性。 我需要通过业务对象维护某种状态 如果你看一下这些类,我认为访问修饰符是不对的。我认为它的结构不是很好。大多数关系都是用公共属性建模的。SubAccount.Account.User.ID延迟加载-除非访问AccountCollection对象,否则不要在用户内部创建AccountColle
我需要访问父对象的属性。
我需要通过业务对象维护某种状态
如果你看一下这些类,我认为访问修饰符是不对的。我认为它的结构不是很好。大多数关系都是用公共属性建模的。SubAccount.Account.User.ID延迟加载-除非访问AccountCollection对象,否则不要在用户内部创建AccountCollection对象。或者,您可以让它与用户同时检索帐户集合,并避免1+9000次数据库访问 有更多的选择性收集检索方法(例如,你打算对9000名用户做什么?如果你需要他们的所有信息,这并不是浪费) 具有较小的“摘要”对象,用于下拉列表和查找等长列表-这些对象是简单的只读业务对象-通常只包含少量信息,可用于检索完整的对象
如果您正在进行分页,用户列表是否加载一次并存储在web服务器中,然后从缓存副本进行分页,还是每次都从数据库中加载集合并由控件进行分页?这个答案最终包含了许多热门词标题。希望我能解释每一个,以及为什么它适用于这里。我认为我在下面介绍的每个概念都值得考虑——它们并不总是适用的,但我发现它们都是我个人在思考系统结构时觉得有价值的东西 单一责任 首先思考每个对象的责任——它的工作是什么?一般来说,一旦你决定为每门课做一份工作,你会发现一个更好的设计。目前,您的很多类都做得太多了,它们持有的逻辑实际上应该作为服务存在 上面的第一个示例是您的用户类:
public class User {
public string ID {get;set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string PhoneNo {get; set;}
public AccountCollection accounts {get; set;}
public User {
accounts = new AccountCollection(this);
}
public static List<Users> GetUsers() {
return Data.GetUsers();
}
}
公共类用户{
公共字符串ID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串PhoneNo{get;set;}
公共帐户集合帐户{get;set;}
公共用户{
账户=新账户集合(此);
}
公共静态列表GetUsers(){
返回Data.GetUsers();
}
}
为什么这提供了一个从数据源检索用户的方法?该功能应该转移到用户服务中
这方面的另一个关键示例是子帐户上的GenerateReport方法—不要将报表生成逻辑与子帐户对象紧密绑定。将其拆分将为您提供更大的灵活性,并减少对子帐户的更改,从而打破报告逻辑
延迟加载
再次看看你的用户类-为什么它在实例化时加载所有用户帐户?是否每次与用户一起工作时都会使用这些对象
通常最好引入延迟加载-仅在需要时检索帐户。当然,有时您希望立即加载(如果您知道您很快就会想要对象,因此希望减少数据库访问),但您应该能够针对这些异常进行设计
依赖注入
这种情况从延迟加载点和单一责任点开始。你有很多硬编码的引用,比如你的数据类。这使得您的设计更加严格——重构数据访问以引入延迟加载,或者改变检索用户记录的方式,因为现在许多类都直接访问数据访问逻辑,这就更加困难了
摘要对象
给Cade Roux一个小提示——我从来没有听说过术语Digest Object,通常称之为轻量级DTO
正如Cade所说,如果您所做的只是显示一个绑定到唯一ID的用户名组合框,那么就没有理由检索包含完整功能用户对象的富列表
引入一个仅存储非常基本的用户信息的轻量级用户对象
这也是引入服务/存储库抽象和某种依赖注入的另一个原因。当您将数据检索从实际对象中封装出来,并且不严格绑定到数据访问实现时,更改从数据存储中检索的对象的类型会变得容易得多
得墨忒耳定律
您的对象对彼此的内部结构了解得太多。允许用户向下钻取帐户,然后再钻取子帐户,这混淆了每个对象的责任。当您不应该设置子帐户信息时,您可以从用户对象设置子帐户信息
我一直在与这个原则斗争,因为钻研继承权似乎很方便。问题是,它将阻止您对每个对象的封装和角色进行有问题的思考
也许不要向用户公开Account对象,而是尝试引入属性和方法来公开Account对象的相关成员。查看GetAccount方法,而不是Account属性,这样您就可以强制自己使用Account对象,而不是将其视为用户的属性。好的,现在只需对代码进行快速注释
public class SubAccount {
public Account account {get; set;} //this is public so that my Data class can access the account, to get the account's user's ID.
public SubAccount(Account account) {
this.account = account;
}
[snip]
}
如果将帐户
属性中的setter传入ctor,然后分配给backing字段,则您甚至不需要该属性中的setter
通过在ctor上传递属性来设置属性是一个很好的实践,但是如果您的
public class SubAccount {
public Account account {get; set;} //this is public so that my Data class can access the account, to get the account's user's ID.
public SubAccount(Account account) {
this.account = account;
}
[snip]
}