如何在代码中首先创建聚簇键

时间:2015-01-22 09:51:21

标签: c# code-first data-annotations

一个人可以有很多同事而一个同事就是一个人。是否可以在ColleagueIdPersonId上制作群集密钥?

好的,我不太确定,但是同事类只是因为数据库应该理解与Person的连接。所以,实际上我不需要Colleague类。我怎么能这样做,数据库知道Person有一个Colleagues的{​​{1}}列表?

在该计划中,我们可以创建Person,然后我们就可以将其他Persons添加到Persons的{​​{1}}列表中!

我的解释感到多云,但我不知道如何用其他任何方式解释它。

同事班:

Persons

人员类:

Colleagues

2 个答案:

答案 0 :(得分:1)

我使用OrmLite v3(不支持复杂的主键)。我在那里使用的工作是创建一个新属性,它是两个键的组合,我用作键:

public class Colleague
{
    public int ColleagueId { get; set; }
    public int PersonId { get; set; }

    [Key]
    public string CombinedId {
        get { return ColleagueId.ToString() + PersonId.ToString(); }
    }
}

我使用string类型来避免得到两个int值的总和(这可能会导致密钥冲突,尽管不完全安全,具体取决于int数字)。当然,您可以根据自己的类型进行调整。

答案 1 :(得分:0)

您基本上希望Person实体之间存在多对多关系。为此,您需要一个连接Person实体对的联结表。如果我们将此实体称为WorkRelationship

class WorkRelationship
{
    [Key]
    [Column(Order = 1)]
    [ForeignKey("Myself")]
    public int MyselfId { get; set; }

    public virtual Person Myself { get; set; }

    [Key]
    [Column(Order = 2)]
    [ForeignKey("Colleague")]
    public int ColleagueId { get; set; }

    public virtual Person Colleague { get; set; }
}

然后我们像这样修改Person

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

    [InverseProperty("Myself")]
    public virtual ICollection<WorkRelationship> WorkRelationships { get; set; }

    public void AddWorkRelationship(Person colleague)
    {
        if (WorkRelationships == null)
        {
            WorkRelationships = new List<WorkRelationship>();
        }

        WorkRelationships.Add(new WorkRelationship { Myself = this, Colleague = colleague });
    }
}

所以你可以看到Person现在有一个WorkRelationships的集合:通过在这个集合中添加一个实体,你不仅可以将这个人链接到他/她的同事,还可以创建反向关系。我还添加了一个辅助方法,以便您可以轻松添加关系。

这是一个非常基本的数据库上下文类,可用于管理这些实体:

sealed class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<WorkRelationship> WorkRelationships { get; set; }

    public IEnumerable<Person> GetColleagues(int personId)
    {
        List<WorkRelationship> relationships =
            WorkRelationships
            .Include(x => x.Myself)
            .Include(x => x.Colleague)
            .Where(x => x.MyselfId == personId || x.ColleagueId == personId)
            .ToList();

        foreach (WorkRelationship relationship in relationships)
        {
            if (relationship.Myself.Id == personId)
            {
                yield return relationship.Colleague;
            }
            else if (relationship.Colleague.Id == personId)
            {
                yield return relationship.Myself;
            }
        }
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
    }
}

我还为此添加了一个帮助方法,用于检索给定人员的同事。

我们现在可以创建一个简单的测试程序来插入和查询人员:

static void Main(string[] args)
{
    var alice = new Person { Name = "Alice" };
    var bob = new Person { Name = "Bob" };
    var colin = new Person { Name = "Colin" };
    var davina = new Person { Name = "Davina" };

    alice.AddWorkRelationship(bob);
    alice.AddWorkRelationship(colin);

    bob.AddWorkRelationship(davina);

    using (var db = new MyContext())
    {
        db.People.AddRange(new[] { alice, bob, colin, davina });
        db.SaveChanges();
    }

    using (var db = new MyContext())
    {
        Console.WriteLine("Bob works with:");
        foreach (Person colleague in db.GetColleagues(bob.Id))
        {
            Console.WriteLine(colleague.Name);
        }
    }

    Console.ReadLine();
}

以下原始答案(包含在上下文中)

如果Colleague 是-a Person,那么你应该像那样建模:

public class Colleague : Person
{
    // don't need any other properties based on what you've posted
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public byte[] Image { get; set; }
    public virtual ICollection<Conversation> Conversations { get; set; }
    public virtual ICollection<Colleague> Colleagues { get; set; }
}

(我已经复制了用于保存同事集合的属性名称。)

EF Code First然后应该创建一个Person表,其中包含额外的Discriminator列,用于区分PersonColleague个实体。

再考虑一下,我甚至不确定你需要单独的Colleague实体。你可能可以逃脱这个:

public class Person
{
    ...
    public virtual ICollection<Person> Colleagues { get; set; }
}

注意ICollection<Person>而不是ICollection<Colleague>