2017-01-10 78 views
-1

我对此很困惑。我无法找到一个专为小酒鬼或傻瓜设计的指南,因为我得到的都是先进的或至少是学过的技术性东西,我忘了。 (不是真的大到数据库时,我还在学习)数据库3种类型的用户

rought outline

所以我发布了一个大致的轮廓我做了一个形象,我一直盯着它几个小时,但我的心不是undecisiveness去任何地方,我加倍每当我感觉自己在正确的轨道上时,就会猜测自己。

无论如何,我应该如何设计表格?

说例如有3种类型的帐户。 1代表正常,2代表培训者,3代表健身房。

我使用帐户表来获取登录帐户的访问级别。所以我对此非常困惑。我很确定所有的表都需要有一个主键。所以我决定每桌上都有身份证。

像userid,trainerid,gymid。

那么我如何将他们FK到账户的表上?我是否将所有3添加为FK?如果它是一个普通用户,那么如果FK和空运(FK)是空的,那么甚至可以接受FK为空?

帐户表也有一个accountid(PK)甚至不知道它是否有用,或者因为我只需要检查帐户表的accesslevel列(我可能知道我什么时候深深地参与它后来现在我只是不能看到帐户表上使用PK,除了你需要每个表的PK)。

所以我在想,我应该只使用用户名作为外键?但可以正常的唯一列是外键?还是需要将它们设置为主键?

另外,关于这三类帐户,他们基本上都有一个配置文件,我应该让另一个表连接到他们名为profile吗?(每个用户类型的用户类型user_profile,trainer_profile,gym_profile )。

+0

这里有很多问题。首先是基本的[数据库设计](http://sqlmag.com/database-performance-tuning/sql-design-why-you-need-database-normalization)并找出你的实体。其次,你有安全问题。 .NET有一些很好的内置功能,如[Identity](https://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity)可以提供帮助。 –

+0

我只是为自己做一个项目,而不是把它们放到网上。如果安全问题是关于散列密码的问题,而不是我计划的问题,但我还没有完成,因为我更专注于获得更清晰的图像,然后在实施它们之后,我会照顾其他细微差别安全等。我只想要一个粗糙的形式,我可以擦亮。 – john

+0

好吧,从您的基本实体开始:帐户,健身房,用户,培训师。主键取决于你 - 我更喜欢[代理键](http://stackoverflow.com/questions/20052799/surrogate-key-vs-natural-key-for-ef),但你可以使用像UserName这样的自然键如果你喜欢。然后在这些表格之间建立关系,EF将完成后台工作。 –

回答

0

也许问题之一是,你立即开始考虑表和ID和外键等。如果你在对象和对象之间的关系中思考,通常会容易得多。

阅读你的照片有点困难。从我收集的文本来看,你有一个帐户的概念,显然有三种类型的帐户:普通,培训人员和健身房老板。这些帐户之间有区别吗?健身房拥有者是否拥有普通用户不具备的属性?或者它只是某种标识。

从您的绘图看来,普通用户似乎拥有用户名,密码和访问级别。培训师也有这些属性?

如果是这样,那么在正常的面向对象的设计,你会说这是一个集合:培训师,正常人和健身房业主都有一个用户名,密码和访问级别。聚合也常被称为构图。有一个小的差异,但对于这个讨论它并不重要。

而不是聚合/合成(对象为一个帐户),你也可以想到继承:对象是一个帐户:教练帐户,健身房老板帐户和普通帐户都是对象,它们都是不同种类的帐户,用户名,密码和访问级别。

在这个例子中,聚合(教练有一个帐户)或继承(教练帐户是一个帐户)没有很大的区别。通常建议是赞成继承聚合enter link description here

请注意:如果您的三个帐户之间的唯一区别是属性的值,那么请考虑将它们全部设为相同类型,并使用属性AccountType向您提供有关信息无论是普通帐户,健身房所有者帐户还是教练帐户。

如果这三者之间的唯一区别是访问级别,则不要创建帐户类型。访问级别将用作帐户类型。

到目前为止,我只谈论面向对象的设计。一旦你设计了你的对象,你可能会想到把它们放在一个数据库中。

让我们假设一个教练,一个健身房老板和一个普通人真的是不同的东西,具有不同的属性。你的班级看起来类似于:

public enum AccessLevel 
{ 
    None, 
    ..., 
    FullAccess, 
} 

public class Account 
{ 
    public string UserName {get; set;} 
    public string Password {get; set;} 
    public AccessLevel AccessLevel {get; set;} 
} 

public class Trainer 
{ 
    public .. some trainer properties {get; set;} 
    // a trainer has an account 
    public Account Account {get; set;} 
} 

public class GymOwner 
{ 
    public ... some gym owner properties {get; set;} 
    public Account Account {get; set;} 
} 

如果你的设计是这样的,你会发现至少你有一个健身房老板桌和一个教练桌。但是如何处理帐户。

一个解决方案是将帐户放在单独的表格中,并向培训师和健身房老板添加一些内容,这样如果您有培训师,您就可以知道帐户表中的哪个项目属于此特定培训师。

此方法通常不用于此设计。如果对象A和对象B有一对一的关系:一个A属于一个B,一个B属于一个A,那么实际上它们可以放在一个表中。如果您使用实体框架并且已经定义了上述类,则帐户属性将作为列添加到教练员表以及作为健身房所有者表的列。优点是获取关于教练员的信息更快,因为这只涉及访问一个表。

关于主键。每个表中的每个元素都应该只有一个主键。这是标识对象的属性。如果您拥有密钥,则可以非常快速地访问所有其他属性。为了让您更容易理解帐户的角色,我在原始代码中省略了ID。

但现在我们已经决定最好让培训师和健身房的老板有一个帐户,那里会有两个桌子:培训师和健身房老板。这些是唯一具有主键的元素。这些类将如下所示:

public class Account 
{ 
    public string UserName {get; set;} 
    public string Password {get; set;} 
    public AccessLevel AccessLevel {get; set;} 
} 

public class Trainer 
{ 
    public int Id {get; set;} 
    public .. some trainer properties {get; set;} 
    // a trainer has an account 
    public Account Account {get; set;} 
} 

public class GymOwner 
{ 
    public int Id {get; set;} 
    public ... some gym owner properties {get; set;} 
    public Account Account {get; set;} 
} 

请注意,没有帐户表,因此帐户不需要密钥。

所以,当你需要一个外键

如果一个教练不会有一个帐户,但几个账户,也许很多帐户,通常称为帐户的集合,那么我们就无法保存该账户再次成为Trainer表中的列。我们必须将培训师的所有账户放在一张单独的表格中,并告诉每个账户所属的培训师。该帐户获得外键至他所属的培训师的主键。

在数据库方面,这被称为一对多关系:一个培训师有很多帐户。

对于实体框架的类会是这样:

public class Account 
{ 
    public int Id {Get; set;} 
    public int TrainerId {get; set;} 

    public string UserName {get; set;} 
    public string Password {get; set;} 
    public AccessLevel AccessLevel {get; set;} 
} 

public class Trainer 
{ 
    public int Id {get; set;} 
    public .. some trainer properties {get; set;} 
    // a trainer has an account 
    public virtual ICollection<Account> Accounts {get; set;} 
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<Trainer> Trainers {get; set;} 
    public DbSet<Account> Accounts {get; set;} 
} 

注意,由于帐户有其表它已经得到了主键。 旁边还有一个TrainerId属性的外键。

我也添加了从DbContext派生的类来访问表。直到知道我只有带培训师的表格和带有帐户的表格。每个表都称为DbSet,DbSet的类型通知实体框架有关表中的列。

由于培训师具有虚拟帐户集合,实体框架知道培训师和帐户之间存在一对多关系,并且由于名称为TrainerId,因此实体框架知道TrainerId是主要的外键该帐户所属的培训师的密钥。

所以,如果你有一个教练的id,你得到这个教练的所有帐户使用以下的Linq语句:

int trainerId = GetMyTrainerId(); 
IEnumerable<Account> accountsOfTrainer = dbContext.Accounts 
    .Where(account => account.TrainerId == trainerId); 

从帐户收集,取其中财产TrainerId等于trainerId所有记录

所以,现在你知道如何设计一个主键,并让外键指向它。

但是健身房老板呢?如果一位健身房老板只有一个账户,就让它拥有一个账户(组合)。但是,如果您的健身房老板也拥有一系列帐户,该怎么办?

如果您只是将健身房老板账户添加到账户表中,那么您会遇到麻烦。外键指向哪个Id?在培训师表或健身房所有者表中的主键?

最安全的方法是创建GymOwnersAccount和TrainersAccount。他们每个人都有自己的表与外键。一个GymOwnersAccount将有一个外键给GymOwners表,一个TrainersAccount将有一个外键给训练者表。

在这里,您也可以决定让GymOwners帐户拥有一个帐户,但似乎更自然地说,一个GymOwners帐户是一种特殊类型的帐户,因此来自帐户。

public class Account 
{ 
    public string UserName {get; set;} 
    public string Password {get; set;} 
    public AccessLevel AccessLevel {get; set;} 
} 

public class GymOwnerAccount : Account 
{ 
    public int Id {get; set;} 
    public int GymOwnerId {get; set;} 
} 
public class TrainerAccount : Account 
{ 
    public int Id {get; set;} 
    public int TrainerId {get; set;} 
} 

public class Trainer 
{ 
    public int Id {get; set;} 
    public .. some trainer properties {get; set;} 
    // a trainer has an account 
    public virtual ICollection<Account> Accounts {get; set;} 
} 

public class GymOwner 
{ 
    public int Id {get; set;} 
    public ... some gym owner properties {get; set;} 
    public virtual ICollection<Account> Accounts {get; set;} 
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<Trainer> Trainers {get; set;} 
    public DbSet<Account> GymOwnerAccounts {get; set;} 
    public DbSet<Account> TrainerAccounts {get; set;} 
} 

还有其他的解决方案成为可能,例如给每个帐户的两个外键,一个健身房老板和一个培训师,在这里你总是需要一个外键设置为0可以很容易地看到,这可能导致维护问题,虽然它不给你任何好处,所以我会建议坚持用GymOwnerAccounts和TrainerAccounts单独的表。

现在我已经进入了数据库中的继承领域,您可以配置丰富的项目。一篇帮助我理解实体框架,以及如何将类,继承,组合转移到数据库的文章是Entity Framework Code First

+0

那是我的大脑刚刚炸过的线路,我可能需要休息一下。 我只想澄清一下3种账户类型。 我打算做一个项目,在那里你可以在网上找到健身房,当你在网上找到一个健身房,你在注册后在这些健身房(在线或irl支付)下注册,你可以选择有培训师可供选择的项目,程序到下一个,培训师将跟踪你的进度,如果你完成了系统将推荐更多的程序。像技能树。 在任何情况下,每种类型的用户都会访问差异函数。 – john

+0

用户拥有个人资料是一个给定的,也是健身房和教练。这就是为什么我很困惑。我只是无法将头部包裹起来,直到设计出我的数据库的粗略轮廓,即使没有具体细节,如果我只是有一个粗略的轮廓,至少有一个代码的方向。 – john

+0

所以你有一个健身房。一个健身房有很多客户(一对多)。一个健身房也有许多训练师和许多健身房项目。每周一次的健身课程(体操课)?每个健身课有一个开始时间,一个停止时间,并由一个(或更多)健身教练带领。每个健身课程都有零或更多的顾客参加。你再次看到:在课堂上思考,而不是在表格中思考。在了解了类和它们之间的关系(HAS/IS,一对多或一对一)之后,您可以了解所需的类和关系,以及您需要哪些表以及哪些主键/外键 –