实体框架代码优先一对一关系

发布于 2024-12-08 17:10:39 字数 981 浏览 4 评论 0原文

我有以下两个模型

public class Account
{
     public int Id { get; set; }
     public string Name { get; set; }
     public int CurrentPeriodId { get; set; }

     [ForeignKey("CurrentPeriodId")]
     public virtual Period CurrentPeriod { get; set; }

     public virtual ICollection<Period> Periods { get; set; }
}

public class Period
{
     public int Id { get; set; }
     public int AccountId { get; set; }
     public DateTime StartDate { get; set; }
     public DateTime EndDate { get; set; }

     public virtual Account Account { get; set; }
}

我正在尝试运行以下查询:

from p in context.Periods
where p.AccountId == accountId &&
      p.Id == p.Account.CurrentPeriodId
select p.StartDate

我收到一个 sql 异常,提示“无效的列名 Account_AccountId”。

我知道我可以从帐户方面处理这个问题并执行类似的操作

from a in context.Accounts
where a.Id == id
select a.CurrentPeriod.StartDate

,但我想知道如何设置关系以使其他查询正常工作。我缺少什么?

I have the following two models

public class Account
{
     public int Id { get; set; }
     public string Name { get; set; }
     public int CurrentPeriodId { get; set; }

     [ForeignKey("CurrentPeriodId")]
     public virtual Period CurrentPeriod { get; set; }

     public virtual ICollection<Period> Periods { get; set; }
}

public class Period
{
     public int Id { get; set; }
     public int AccountId { get; set; }
     public DateTime StartDate { get; set; }
     public DateTime EndDate { get; set; }

     public virtual Account Account { get; set; }
}

And I am trying to run the following query:

from p in context.Periods
where p.AccountId == accountId &&
      p.Id == p.Account.CurrentPeriodId
select p.StartDate

And I get a sql exception saying "Invalid column name Account_AccountId".

I know I could approach this from the Account side and do something like

from a in context.Accounts
where a.Id == id
select a.CurrentPeriod.StartDate

But I would like to know how to setup the relationship to get the other query to work. What am I missing?

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

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

发布评论

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

评论(1

南渊 2024-12-15 17:10:39

我认为你的实施是错误的。 AFAIK,您无法在 EF 中使用此方法定义一对一关系。
查看生成的数据库,您在 Periods 表中定义了一个 Account_Id 列。以下是您必须定义的内容:

public class Account
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CurrentPeriodId { get; set; }
    public virtual Period CurrentPeriod { get; set; }
    public virtual ICollection<Period> Periods { get; set; }
}

public class Period
{
    public int Id { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

然后,上下文和初始化程序:

public class TestContext : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Period> Periods { get; set; }

static TestContext()
{ 
    Database.SetInitializer(new DbInitializer());
}

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Account>().HasRequired(a => a.CurrentPeriod).WithMany().HasForeignKey(a => a.CurrentPeriodId);
    }
}

class DbInitializer : DropCreateDatabaseAlways<TestContext>
{
    protected override void Seed(TestContext context)
    {
        context.Database.ExecuteSqlCommand("ALTER TABLE Accounts ADD CONSTRAINT uc_Period UNIQUE(CurrentPeriodId)");
    }
}

有关一对一关系的更多信息,请阅读 Manavi 先生的博客系列,网址为 这个地址
更新
根据您的评论,如果您希望从 Period 引用 Account,您可以在帐户的主键上添加 ForeignKey 属性。

一个很好的示例位于此地址(标题为“映射一对零或一对一关系”的部分)

I think your implementation is wrong. AFAIK, You cannot define one-to-one relationship using this approach in EF.
Take a look at your generated database, you have an Account_Id column defined in your Periods table. Here's what you have to define:

public class Account
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int CurrentPeriodId { get; set; }
    public virtual Period CurrentPeriod { get; set; }
    public virtual ICollection<Period> Periods { get; set; }
}

public class Period
{
    public int Id { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

Then, context and initializer:

public class TestContext : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Period> Periods { get; set; }

static TestContext()
{ 
    Database.SetInitializer(new DbInitializer());
}

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Account>().HasRequired(a => a.CurrentPeriod).WithMany().HasForeignKey(a => a.CurrentPeriodId);
    }
}

class DbInitializer : DropCreateDatabaseAlways<TestContext>
{
    protected override void Seed(TestContext context)
    {
        context.Database.ExecuteSqlCommand("ALTER TABLE Accounts ADD CONSTRAINT uc_Period UNIQUE(CurrentPeriodId)");
    }
}

For more information about One-To-One relationship, read Mr. Manavi's blog series at this address.
Update:
Based on your comment, if you want to have a reference to Account from Period, You can put a ForeignKey attribute on your account's primary key.

A good sample is located at this address (the part with title "Map a One to Zero or One Relationship")

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