0

Following on from earlier posts today:

Entity framework one to zero or one relationship without navigation property

Understanding ForeignKey attribute in entity framework code first

I'm now trying to configure the following relationships:

Item1 has optional RawData Item2 has optional RawData Item3 has optional RawData

RawData must be attached to either Item1, Item2 or Item3 - it would not be expected to exist on its own.

Current structure is:

class ItemX
{
    [Key]
    public int Id { get; set; }

    public int? RawDataId { get; set; }
    [ForeignKey("RawDataId")]
    public virtual RawData RawData { get; set; }
}

public class RawData
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    //other properties
}

I thought this might be configured using:

modelBuilder.Entity<Item1>().HasOptional(d => d.RawData).WithOptionalPrincipal().WillCascadeOnDelete(true);
modelBuilder.Entity<Item2>().HasOptional(d => d.RawData).WithOptionalPrincipal().WillCascadeOnDelete(true);
modelBuilder.Entity<Item3>().HasOptional(d => d.RawData).WithOptionalPrincipal().WillCascadeOnDelete(true);

But this gave the following error:

The ForeignKeyAttribute on property 'RawData' on type 'Item1' is not valid. The foreign key name 'RawDataId' was not found on the dependent type 'RawData'.

This is the same error I was dealing with in an earlier post today. In that one I understand the reason it wasn't working due to a shared primary key. But that can't be the case in this example as RawData can't share a primary key with Item1 as Item2 might have the same id.

Thanks for any help.

Edit

I've got it working using:

modelBuilder.Entity<Item1>().HasOptional(d => d.RawData).WithMany().HasForeignKey(d=>d.RawDataId).WillCascadeOnDelete(true);
//etc.

Database looks ok. Seems a little odd to be describing as WithMany though but perhaps this is what is required when then are multiple relationships??

Community
  • 1
  • 1
Mark007
  • 345
  • 1
  • 4
  • 8

1 Answers1

0

You need to include Item1, Item2, and Item3 in the RawDataclass:

public class RawData
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public virtual Item1 i1 {get;set;}
    public virtual Item2 i2 {get;set;}
    public virtual Item3 i3 {get;set;}
    //other properties
}
pquest
  • 3,151
  • 3
  • 27
  • 40
  • I can see how this helps define the relationship but shouldn't it be possible without the navigation property? – Mark007 Feb 18 '14 at 18:11
  • Seems to work if I describe as WithMany() in the fluent API but this seems wrong in principle.. – Mark007 Feb 18 '14 at 19:11
  • it's a little weird to get used to, but try it. It will work. You won't even need any code in the fluent API. – pquest Feb 18 '14 at 19:30
  • I want to use fluent api though as I want to enable cascade deletes. – Mark007 Feb 18 '14 at 19:36
  • Isn't cascade delete the default? – pquest Feb 18 '14 at 19:49
  • Good question to which I don't know the answer. It may be although I have a feeling I read somewhere that there are conventions for different relationship types. I've not tried the above as things seem to be working with WithMany(). I'm keen to understand how this relationship should be setup with fluent but will have a play with your suggestion later on too. – Mark007 Feb 18 '14 at 20:11
  • Just found this that suggests have to use 1 to Many even though not really: http://stackoverflow.com/questions/17346231/entity-framework-optionaloptional-relationship – Mark007 Feb 18 '14 at 21:32