如何在 Entity Framework 4.1 的 Code-First Fluent API 中以编程方式定义关系

发布于 2024-10-23 22:44:56 字数 411 浏览 1 评论 0原文

我正在玩新的 EF4.1 unicorn love。

我试图理解使用代码优先以编程方式定义几个简单 POCO 之间的关系的不同方式。

我如何定义以下 =>

  1. 1 个团队拥有 0 个用户。 (并且 User 位于 1 Team 中)
  2. 1 User 有 0 或 1 个 Foo(但是Foo 没有返回到 User 的属性)
  3. 1 User 有 1 UserStuff

I'm playing around with the new EF4.1 unicorn love.

I'm trying to understand the different ways I can use code-first to programatically define my relationships between a few simple POCO's.

How can I define the following =>

  1. 1 Team has 0-many Users. (and a User is in 1 Team)
  2. 1 User has 0-or-1 Foo's (but a Foo has no property going back to a User)
  3. 1 User has 1 UserStuff

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

燕归巢 2024-10-30 22:44:56

这里有您正在寻找的示例:

public class User
{
    public int Id { get; set; }
    ...
    public Foo Foo { get; set; }
    public Team Team { get; set; }
    public UserStuff UserStuff { get; set; }
}

public class Team
{
    public int Id { get; set; }
    ...
    public ICollection<User> Users { get; set; }
}

public class Foo
{
    public int Id { get; set; }
    ...
}

public class UserStuff
{
    public int Id { get; set; }
    ...
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Team> Teams { get; set; }
    public DbSet<UserStuff> UserStuff { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasRequired(u => u.Team)
            .WithMany(t => t.Users);

        modelBuilder.Entity<User>()
            .HasOptional(u => u.Foo)
            .WithRequired();

        modelBuilder.Entity<User>()
            .HasRequired(u => u.UserStuff)
            .WithRequiredPrincipal();
    }
}

Here you have examples you are looking for:

public class User
{
    public int Id { get; set; }
    ...
    public Foo Foo { get; set; }
    public Team Team { get; set; }
    public UserStuff UserStuff { get; set; }
}

public class Team
{
    public int Id { get; set; }
    ...
    public ICollection<User> Users { get; set; }
}

public class Foo
{
    public int Id { get; set; }
    ...
}

public class UserStuff
{
    public int Id { get; set; }
    ...
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Team> Teams { get; set; }
    public DbSet<UserStuff> UserStuff { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasRequired(u => u.Team)
            .WithMany(t => t.Users);

        modelBuilder.Entity<User>()
            .HasOptional(u => u.Foo)
            .WithRequired();

        modelBuilder.Entity<User>()
            .HasRequired(u => u.UserStuff)
            .WithRequiredPrincipal();
    }
}
辞取 2024-10-30 22:44:56

让我们介绍一些特定的类来说明解决方案:

public class Account
{
    public long ID { get; set; }
    public virtual User User { get; set; }
}

public class User
{
    public long ID { get; set; }
    public virtual Account Account { get; set; }
    public virtual Team Team { get; set; }
}

public class Team
{
    public long ID { get; set; }
    public long CompanyID { get; set; }

    public virtual Company Company { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

public class Company
{
    public long ID { get; set; }
}

我正在使用一个辅助类来使映射类变得不那么冗长:

internal abstract class AbstractMappingProvider<T> : IMappingProvider where T : class
{
    public EntityTypeConfiguration<T> Map { get; private set; }

    public virtual void DefineModel( DbModelBuilder modelBuilder )
    {
        Map = modelBuilder.Entity<T>();

        Map.ToTable( typeof(T).Name );
    }
}

现在介绍映射。我们先进行“1:1”映射。在我的示例中,用户和帐户是 1:1 相关的,并且共享相同的主键(其中只有一个是身份列,在本例中是 Account.ID)。

internal class UserMapping : AbstractMappingProvider<User>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasRequired( e => e.Account ).WithRequiredDependent( r => r.User ).WillCascadeOnDelete( true );
    }
}

internal class AccountMapping : AbstractMappingProvider<Account>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasRequired( e => e.User ).WithRequiredPrincipal( r => r.Account ).WillCascadeOnDelete( true );
    }
}   

在以下映射中,我们指定一个团队有 (0..n) 个用户,而单个用户恰好位于一个团队中(必需)。我们还指定一个团队可以拥有一个公司,但公司不公开团队列表。

internal class TeamMapping : AbstractMappingProvider<Team>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasOptional( e => e.Company ).WithMany().HasForeignKey( e => e.CompanyID );
        Map.HasMany( e => e.Users ).WithRequired( r => r.Team );
    }
}   

internal class CompanyMapping : AbstractMappingProvider<Company>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
    }
}

希望这有帮助!

Lets introduce a few specific classes to illustrate the solutions:

public class Account
{
    public long ID { get; set; }
    public virtual User User { get; set; }
}

public class User
{
    public long ID { get; set; }
    public virtual Account Account { get; set; }
    public virtual Team Team { get; set; }
}

public class Team
{
    public long ID { get; set; }
    public long CompanyID { get; set; }

    public virtual Company Company { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

public class Company
{
    public long ID { get; set; }
}

I'm using a helper class to make the mapping classes a bit less verbose:

internal abstract class AbstractMappingProvider<T> : IMappingProvider where T : class
{
    public EntityTypeConfiguration<T> Map { get; private set; }

    public virtual void DefineModel( DbModelBuilder modelBuilder )
    {
        Map = modelBuilder.Entity<T>();

        Map.ToTable( typeof(T).Name );
    }
}

Now for the mappings. Lets do the "1:1" mapping first. In my example user and account are 1:1 related and share the same primary key (only one of them will be an identity column, which in this case is the Account.ID).

internal class UserMapping : AbstractMappingProvider<User>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasRequired( e => e.Account ).WithRequiredDependent( r => r.User ).WillCascadeOnDelete( true );
    }
}

internal class AccountMapping : AbstractMappingProvider<Account>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasRequired( e => e.User ).WithRequiredPrincipal( r => r.Account ).WillCascadeOnDelete( true );
    }
}   

In the following mappings we specify that a team has (0..n) users, while a single user is in exactly one team (required). We also specify that a team can have a company, but company does not expose a list of teams.

internal class TeamMapping : AbstractMappingProvider<Team>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
        Map.HasOptional( e => e.Company ).WithMany().HasForeignKey( e => e.CompanyID );
        Map.HasMany( e => e.Users ).WithRequired( r => r.Team );
    }
}   

internal class CompanyMapping : AbstractMappingProvider<Company>
{
    public override void DefineModel( DbModelBuilder modelBuilder )
    {
        base.DefineModel( modelBuilder );
    }
}

Hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文