简体   繁体   English

数据库 model 到 object 面向设计?

[英]Database model to object oriented design?

How would I design classes say in c# to represents a database model?我将如何设计 c# 中的类来表示数据库 model?

Given the following tables and fields for a database,给定数据库的以下表和字段,

Table: Employee表:员工

Pk EmpID
   Lname
   Fname
   Adress
Fk DeptID

Table: Department表:部门

Pk DeptID
   DeptName
   Location

Ok so now I want to make 2 classes in C#, one for Employee and one for Department.好的,现在我想在 C# 中创建 2 个类,一个用于员工,一个用于部门。 The part I get hung up on is the foreign keys.我挂断的部分是外键。 Should I use the foreign keys in my design for the objects, or should I put a reference in my Employee class of the Department,or should I put a list of employee references in my Department class,or should I do both?我应该在我的对象设计中使用外键,还是应该在部门的员工 class 中放置参考,或者我应该在部门 class 中放置员工参考列表,还是应该两者都做? I know if I use foreign keys, it will be less efficient because I will have to search through a list of primary keys that match the foreign key but I probably should include them in the design anyway.我知道如果我使用外键,效率会降低,因为我必须搜索与外键匹配的主键列表,但无论如何我可能应该将它们包含在设计中。

Don't use "foreign keys" in your objects.不要在对象中使用“外键”。 Use references;使用参考; each Department should have a list of Employees.每个部门都应该有一份员工名单。 Depending on whether or not you have a need to backreference from Employee to their Department, make the determination as to whether Employee will have a reference to Department.根据您是否需要从 Employee 反向引用他们的 Department,确定 Employee 是否会引用 Department。

Elaboration on @Paul Sonier answer...详细说明@Paul Sonier 的答案...

PS I'm using business layer , business classes in a general sense, not as jargon of some particular technical design pattern. PS我使用的是业务层,一般意义上的业务类,而不是某些特定技术设计模式的行话。

The specific problems of using database keys使用数据库键的具体问题
Using database keys is going to cause an explosion of coding overhead to keep objects and the database in synch.使用数据库键将导致编码开销激增,以保持对象和数据库同步。 As the need to add, change, delete objects happens (via user GUI) you'll be jumping through hoops like crazy.由于需要添加、更改、删除对象(通过用户 GUI),您将像疯了一样跳过箍。 How would you create a child object when the parent object does not exist yet in the database?当数据库中尚不存在父 object 时,您将如何创建子 object? Imagine trying to do this with any N-level data structure.想象一下尝试使用任何 N 级数据结构来执行此操作。

Always design business classes without regard to data storage始终设计业务类而不考虑数据存储
Business layer classes should faithfully reflect the business rules, jargon, concepts, and context.业务层类应该忠实地反映业务规则、行话、概念和上下文。 Polluting this "idea space" with non-business stuff with details about storing or displaying data is bad in the long run.从长远来看,用有关存储或显示数据的细节来污染这个“想法空间”是不好的。 Hear me now and believe me later.现在听我说,以后相信我。

Business classes based on some particular database table layout (and it's keys, etc.) is going to make it disastrously difficult to write code for validating rules, creating proper state of those objects, and so on.基于某些特定数据库表布局(及其键等)的业务类将使编写代码以验证规则、创建这些对象的正确 state 等变得极其困难。 This is on top of the problem of keeping the object IDs in synch w/ the database.这是保持 object ID 与数据库同步的问题之上。

Maximize Decoupling of Business layer and Data layer最大化业务层和数据层的解耦
The example shown in your question is a tempting deception.您问题中显示的示例是一个诱人的欺骗。 Some of your business classes may map very well to your database design.您的一些业务类可能 map 非常适合您的数据库设计。 And consequently the primary and foreign keys may seem to fit as well.因此,主键和外键似乎也很合适。

BUT in any non-trivial application the database model will deviate.但是在任何重要的应用程序中,数据库 model都会发生偏差。 If not now, later.如果不是现在,以后。 It will deviate for the purposes of database integrity, efficiency, and speed.出于数据库完整性、效率和速度的目的,它会有所偏差。 And what does this have to do with the business model?而这与业务 model 有什么关系? Nothing.没有什么。

Indicators that you're doing things right表明您做对了事情的指标

  1. You can instantiate a business object without an existing database您可以在没有现有数据库的情况下实例化业务 object

  2. Each object can reference it's "children" without requiring special keys created outside the business class model.每个 object 都可以引用它的“子项”,而无需在业务之外创建特殊密钥 class model。

  3. Each business object on its own can validate, enforce, flag, etc. all of it's own rules, even trivial ones like "can't be blank".每个业务 object 都可以自己验证、执行、标记等所有规则,甚至是“不能为空白”之类的琐碎规则。 Business rule validation for composite classes/objects is class design & analysis activity - not database design activity.复合类/对象的业务规则验证是 class 设计和分析活动 - 不是数据库设计活动。

First, if possible I would suggest using a tool like NHibernate, the Entity Framework, or Linq to SQL to do the object to relational mapping for you. First, if possible I would suggest using a tool like NHibernate, the Entity Framework, or Linq to SQL to do the object to relational mapping for you. But, if you don't want to do that, I'd probably design my object model like this:但是,如果您不想这样做,我可能会像这样设计我的 object model:

public class Employee
{
    public int Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public Address Address { get; set; } 
    public Department Department { get; set; }
}

public class Department
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Location { get; set; }
    public ICollection<Employee> Employees { get; set; }
}

I don't want to oversimplify but if you have navigation properties from Employee => Department or Department => Employee is pretty specific to the needs of your application.我不想过分简化,但如果您有来自 Employee => Department 或 Department => Employee 的导航属性,则非常适合您的应用程序的需求。

However, as a rule of thumb, I tend to put navigation properties from the top of the heirarchy down.但是,根据经验,我倾向于将导航属性从层次结构的顶部向下放置。 That means I would have Department.Employees but not Employee.Departments.这意味着我将拥有 Department.Employees 而不是 Employee.Departments。

Again, this is specific to you, but it seems pretty unlikely that you would ever need to get the Department object from every single Employee.同样,这是针对您的,但您似乎不太可能需要从每个员工那里获得部门 object。 So, lookup with a key inside the Employee class something like this:因此,使用 Employee class 中的键进行查找,如下所示:

class Employee {

    public int[] DepartmentIds { get; set; }
    public List<Department> Departments {
        get {
            return YourStaticReference.DepartmentList
                .Where(x => this.DepartmentIds.Contains(x.DepartmentId));
        }
    }
}

See?看? Best of luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM