【问题标题】:Complex relationships / access control with ASP.NET MVC 3 and EF 4.1 and POCO与 ASP.NET MVC 3 和 EF 4.1 和 POCO 的复杂关系/访问控制
【发布时间】:2012-01-18 14:44:48
【问题描述】:

我正在从事具有以下条件的项目:

  • Visual Studio 2010
  • ASP.NET MVC 3
  • EF 4.1(如果推荐可以使用其他东西)
  • 代码优先

我正在尝试对以下内容进行建模,但我一直在思考如何做到最好。

我有这些物品。

public class Facility
{
    public virtual int FacilityId;
    public virtual string Name;
    public virtual List<TaskCategory> TaskCategories;
}

public class TaskCategory
{
    public virtual int TaskCategoryId;
    public virtual string Name;
}

public class User
{
    public virtual int UserId;
    public virtual string Username;
}

Facility 和 TaskCategory 是多对多的关系 设施和用户是一对多的关系(一个设施可以有多个用户,一个用户只能属于一个设施)

现在我需要一些方法来连接这三个对象,以便满足以下条件: - 在系统中,应该能够将用户连接到某个设施和某个 TaskCategory

在传统数据库中,我会这样建模:

User_id, Facility_id, TaskCategory_id
1,       1,           1
1,       1,           2
2,       1,           1
1,       2,           1

这意味着用户 1 可以访问设施 1 中的任务类别 1 和 2,以及设施 2 中的任务类别 1。 用户 2 将有权访问设施 1 中的 TaskCategory 1。

这是否有意义,我将如何在与 EF 4.1(或其他 ORM)一起使用的面向对象环境中执行此操作。

更新: 以下代码是我最终使用的(一些不相关的部分不包括在内):

public class Facility
{
    public int Id { get; set; }
    public string Name { get; set; }

    private ICollection<FacilityMembership> _facilityMembership;
    public virtual ICollection<FacilityMembership> FacilityMembership
    {
        get { return_facilityManager ?? (_facilityManager = new HashSet<FacilityMembership>(); }
        set { _facilityManager = value; }
    }
}

}

public class TaskCategory
{
    public int Id { get; set; }
    public string Name { get; set; }

    private ICollection<FacilityMembership> _taskMemberships;
    public virtual ICollection<FacilityMembership> TaskMemberships
    {
        get { return _taskMemberships?? (_taskMemberships= new HashSet<FacilityMembership>()); }
        set { _taskMemberships = value; }
    }
}

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }

    private ICollection<FacilityMembership> _facilityMembership;
    public virtual ICollection<FacilityMembership> FacilityMembership
    {
        get { return_facilityManager ?? (_facilityManager = new HashSet<FacilityMembership>(); }
        set { _facilityManager = value; }
    }
}

public class FacilityMembership
{
    public int Id { get; set; }
    public int FacilityId { get; set; }
    public int UserId { get; set; }
    private ICollection<TaskCategory> _taskCategories;
    public virtual ICollection<TaskCategory> TaskCategories
    {
        get { return _taskCategories ?? (_taskCategories = new HashSet<TaskCategories>()); }
        set { _taskCategories = value; }
    }
}

然后通过fluent api映射:

        modelBuilder.Entity<FacilityMembership>().HasKey(fm => fm.Id);
        modelBuilder.Entity<FacilityMembership>()
                    .HasMany(fm => fm.TaskCategories)
                    .WithMany(tc => tc.FacilityMemberships)
                    .Map(m =>
                             {
                                 m.MapLeftKey("FacilityMembershipId");
                                 m.MapRightKey("TaskCategoryId");
                             });

【问题讨论】:

  • 您需要在 Facility 和 User 之间建立关系..我认为缺少..
  • 它成立了,也许我在上面的例子中简化了很多。这些类有更多的属性。实际上,用户拥有“公共虚拟列表 设施”的属性

标签: c# entity-framework-4 ef-code-first poco code-first


【解决方案1】:

问题:设施有任务,用户可以拥有彼此不相关的设施和任务?如果是这样,你会在你建议的那个桌子上放哪个名字?您可以使用该“名称”创建一个类。

如果没有,您的用户可以只拥有一组任务,您可以访问设施做

return Tasks.Select(x => x.Facility).Distinct();

另一种选择是在您的 User 类中同时包含这两个集合。

【讨论】:

  • 设施有任务,但用户没有直接的任务,只能通过他们“所属”的设施。也许我以错误的方式思考关系?系统的核心是设施,对它们来说,任务是生成的。分配给设施的 TaskCategories 是为了在计划的运行中生成正确的任务。一个设施可以有许多“看门人”,每个人只被允许将某个 TaskCategory 的任务标记为该设施的已完成。然后他们就可以拥有另一个设施上的其他 TaskCategories 的权限。
  • 因此,您的 User 类中似乎只有一个设施集合,而您的 Facility 类中只有一个任务集合。从 db 模型的角度来看,您的表 Task 将有一个外键到设施,而设施将有一个外键到用户。如果用户和设施之间的关系是多对多的,那么您将需要“中间”表。
【解决方案2】:

您的传统数据库模型表明它是一种多对多关系(用户与设施),具有附加属性(任务)。在 EF 中没有什么神奇的方法可以做到这一点,它与在数据库中的操作相同,只是多了一个表/实体。

public class User {
  ICollection<FacilityTask> FacilityTask {get; set;}
}

public class FacilityTask {
  public Facility Facility {get; set;}
  public Task Task {get; set;}
}

or 

public class FacilityTasks {
  public Facility Facility {get; set;}
  public ICollection<Task> Task {get; set;}
}

可能有比 FacilityTasks 更好的命名方案,也许是 FacilityMembership?用户属于设施,并且有与该成员相关的任务。

【讨论】:

  • 我使用了一个额外的实体,称为 FacilityTaskCategoryUser(Facility、TaskCategory、User)。我现在应该以某种方式将我解决它的方式添加到我原来的问题中吗?由于您的回答,我认为这不是我想出的最佳实践解决方案,但它现在有效。
  • 编辑您的问题并将您的解决方案放在那里并没有什么坏处,您可以帮助其他人或从某人那里获得有关如何使其变得更好的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2011-09-29
  • 2011-10-12
  • 2023-01-24
  • 2012-01-12
  • 2011-10-06
相关资源
最近更新 更多