Search code examples
entity-framework-4pococode-firstentity-framework-ctp5ef-code-first

Entity Framework 4 - One-To-Many Relationship with a view with CTP5 (code first)


I'm attempting to map a 1-M relationship between two entities where the first one is normally mapped to a table and the second one is taken from a view.

The involved entities are:

public class Institute
{
    public int Id { get; set; }
    public string Name { get; set; }
    //...
    public virtual ICollection<Text> Texts { get; set; }
}

public class Text
{
    public int InstituteId { get; set; }
    public int TextId { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
    public bool IsRequired { get; set; }
    public int? MaxLength { get; set; }
}

The relevant mapping code is:

private void MapInstituteText(EntityTypeConfiguration<InstituteText> text)
{
    //From a view
    text.HasKey(i => i.InstituteId)
        .ToTable("vwInstituteTexts");

    text.Property(i => i.InstituteId)
        .HasColumnName("FKInstituteID")
        .IsRequired();

    text.Property(i => i.TextPropertyId)
        .HasColumnName("FKTextPropertyID")
        .IsRequired();

    text.Property(i => i.Name)
        .HasColumnName("Name")
        .IsRequired();

    text.Property(i => i.Value)
        .HasColumnName("Value");

    text.Property(i => i.IsRequired)
        .IsRequired();

    text.Property(i => i.MaxLength);
}

private void MapInstitute(EntityTypeConfiguration<Institute> institute)
{
    institute.HasKey(i => i.Id)
        .ToTable("Institutes");

    institute.Property(i => i.Id)
        .HasColumnName("ID")
        .IsRequired();

    institute.Property(i => i.Name)
        .HasColumnName("Name")
        .HasMaxLength(128)
        .IsRequired();

    institute
        .HasMany(i => i.Texts)
        .WithRequired()
        .HasForeignKey(t => t.InstituteId);
}

The problem is that the model is not validated:

Initialization method Studentum.Core.Tests.InstituteTests.Initialize threw exception. System.TypeInitializationException: System.TypeInitializationException: The type initializer for 'Studentum.Core.FluentCoreRepositoryFactory' threw an exception. ---> System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:

System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'Institute_InnerInstituteTexts_Target' in relationship 'Institute_InnerInstituteTexts'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be 1. (the names of the exception can not match exactly because I recreated some of the code specifically for this post)

If I remove the ".HasForeignKey(t => t.InstituteId);" the generated query contains a reference to a field called InstituteId1 which is not present in the queried view

exec sp_executesql N'SELECT 
[Extent1].[FKInstituteID] AS [FKInstituteID], 
[Extent1].[FKTextPropertyID] AS [FKTextPropertyID], 
[Extent1].[Name] AS [Name], 
[Extent1].[Value] AS [Value], 
[Extent1].[IsRequired] AS [IsRequired], 
[Extent1].[MaxLength] AS [MaxLength], 
[Extent1].[InstituteId1] AS [InstituteId1]
FROM [institute].[vwInstituteTexts] AS [Extent1]
WHERE [Extent1].[InstituteId1] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1360

Any suggestion? Thanks.


Solution

  • Apparently your View seems to be not having the required Keys. Try changing

    text.HasKey(i => i.InstituteId)
            .ToTable("vwInstituteTexts");
    

    to

    
    text.HasKey(i => new {i.InstituteId, i.TextId}).ToTable("vwInstituteTexts")
    

    this will help recognize the relationship as well the key TextId.