简体   繁体   English

实体框架6导航属性别名?

[英]Entity Framework 6 Navigation property alias?

I have these two classes: 我有这两节课:

public class Foo
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    // ...

    // Foo has N bars, 1 of which is primary
    [ForeignKey("Bar")]
    public int? PrimaryBarId { get; set; }
    public virtual Bar PrimaryBar { get; set; }
}

public class Bar {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    // ...

    // Foo -> Bar == 1:N
    [ForeignKey("Foo")]
    public int FooId { get; set; }
    public virtual Foo Foo { get; set; }
}

EF now expects me to create a property BarId and Bar on Foo but I don't want that. EF现在希望我在Foo上创建一个BarIdBar属性,但我不希望这样。 I want the property to be named Primary Bar. 我希望将该属性命名为Primary Bar。 I have a 1:N relationship on Foo -> Bar which is reflected elsewhere and not of interest for this question. 我在Foo > Bar上具有1:N的关系,这在其他地方反映出来,对此问题不感兴趣。

EF keeps telling me: EF一直告诉我:

The ForeignKeyAttribute on property 'PrimaryBarId' on type 'XyFoo' is not valid. The navigation property 'Bar' was not found on the dependent type 'XyFoo'. The Name value should be a valid navigation property name.

How do I convince EF to use the PrimaryBar (and PrimaryBarId ) properties (preferrably with an attribute, although using the DbModelBuilder in the OnModelCreating override is an option too? 如何说服EF使用PrimaryBar (和PrimaryBarId )性能(最好有一个属性,虽然使用DbModelBuilderOnModelCreating覆盖是一个选项吗?

EDIT 编辑

Figured it out. 弄清楚了。 I was missing a: 我错过了一个:

public virtual ICollection<Bar> Bar { get; set; }

on my Foo class. 在我的Foo班上。 See here for the explanation. 参见这里的解释。

As per the documentation , the Name provided to the ForeignKeyAttribute should be the property name not the type or table name. 根据文档 ,提供给ForeignKeyAttributeName应该是属性名称,而不是类型或表名称。 So change your code to this: 因此,将您的代码更改为此:

public int? PrimaryBarId { get; set; }
[ForeignKey("PrimaryBarId")]
public virtual Bar PrimaryBar { get; set; }

Or: 要么:

[ForeignKey("PrimaryBar")]
public int? PrimaryBarId { get; set; }
public virtual Bar PrimaryBar { get; set; }

First things first. 首先是第一件事。

If your FK property is a nullable int like I see in your code, your relationship will be 0..1-N and not 1-N as it is a nullable foreign key. 如果您的FK属性是可空的int(如我在代码中看到的那样),则您的关系将是0..1-N而不是1-N,因为它是可空的外键。

Second, I am not very familiar with attribute syntax as it's not ideal to describe your model, and it clutters your object with EF related data. 其次,我对属性语法不是很熟悉,因为描述模型并不理想,并且它会使对象与EF相关数据杂乱无章。 The preferred approach is to declare EF mappings in a separate class which inherits EntityTypeConfiguration<T> where T is your class. 首选方法是在一个单独的类中声明EF映射,该类继承EntityTypeConfiguration<T> ,其中T是您的类。

Now given your classes, first of all you must add a property on Bar that maps the N reference, like this: 现在给定类,首先必须在Bar上添加一个映射N引用的属性,如下所示:

public virtual ICollection<Foo> Foos {get;set;}

Then you can declare an EntityTypeConfiguration<Bar> that, among other settings like defining the primary key and property->column name translation if they don't match, will contain: 然后,您可以声明一个EntityTypeConfiguration<Bar> ,其中包括定义主键和property->列名转换(如果它们不匹配)等其他设置,其中将包含:

this
  .HasMany(p => p.Foos)
  .WithOptional(p => p.PrimaryBar)
  .HasForeignKey(p => p.PrimaryBarId);

If your FK was an int instead of int? 如果您的FK是int而不是int? you would have used WithRequired instead of WithOptional . 您将使用WithRequired而不是WithOptional

According to MSDN Name parameter is not the entity name but the navigation property name (in your case, as it's a bit more complicated than that). 根据MSDN,名称不是实体名称,而是导航属性名称(在您的情况下,因为这要复杂一些)。

You should change your code from: 您应该从以下位置更改代码:

[ForeignKey("Bar")]

to: 至:

[ForeignKey("PrimaryBar")]

I'm terribly sorry, but none of the answers were correct. 非常抱歉,但所有答案均不正确。 That is: they are correct (probably) but I posted my example code for the question wrong. 也就是说:它们正确的(可能),但是我针对错误的问题发布了示例代码。 First I forgot to rename some types/properties, then I found a mistake in the the errormessage I posted. 首先,我忘记重命名某些类型/属性,然后在发布的错误消息中发现一个错误。 And finally it turns out I forgot to post the following code I had on my Bar class: 最后,事实证明我忘了在Bar类上发布以下代码:

class Bar {
    //Didn't post this code:
    [ForeignKey("Foo")]
    public int FooId { get; set; }
    public virtual Foo Foo { get; set; }
}

This code was for the 1:N Foo has to Bar . 该代码用于1:N Foo必须Bar But since the PrimaryBar property implies a 1:0..1 relation EF got confused I guess. 但是由于PrimaryBar属性暗示了EF为1:0..1的关系,我猜想很困惑。 What I was missing was the following on my Foo class to contain the 1:0..N with Bar : 我所缺少的是在我的Foo类上的以下内容,其中包含带有Bar的1:0..N:

class Foo {
    public virtual ICollection<Bar> Bars { get; set; }
}

I added this collection et voila; 我添加了这个集合等等。 everything works fine now. 现在一切正常。

Oh, I did have to change the ForeignKey to PrimaryBar instead of Bar indeed as most answers suggested. 哦,正如大多数答案所建议的,我确实必须将ForeignKey更改为PrimaryBar而不是Bar

I'm terribly sorry and mea culpa: all f*ckups were mine and my own only. 非常抱歉,我是罪魁祸首:所有的朋友都是我的,只有我一个。 I usually don't prefer to post "Foo/Bar/Baz" code instead of actual code but in this case it was a bit difficult and the classes would raise (unrelated) questions on their own which I didn't want to discuss :P 我通常不喜欢发布“ Foo / Bar / Baz”代码,而不是实际代码,但是在这种情况下,这有点困难,并且类会自己提出(不相关的)问题,而我不想讨论: P

I have upvoted all answers as a "thank you"; 我把所有答案都赞为“谢谢”。 however since none of them was the actual solution, again because of my being a dumbass and posting incorrect code/information, I have posted my own answer. 但是,由于它们都不是真正的解决方案,再次由于我笨拙,并发布了错误的代码/信息,所以我发布了自己的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM