Web API 2 OData EDM 异常

3
我有以下代码:

public class AwardTitle
{
    public int AwardTitleId
    {
        get;
        set;
    }

    public int? EpisodeId
    {
        get;
        set;
    }

    public virtual AwardEpisode Episode
    {
        get;
        set;
    }
}

public class AwardEpisode
{
    public int EpisodeId
    {
        get;
        set;
    }
}

public static class WebApiConfig
{
    public static void Register( HttpConfiguration config )
    {
        config.Routes.MapODataRoute( "ODataRoute", "api", GetImplicitEDM( ) );
    }
}

private static Microsoft.Data.Edm.IEdmModel GetImplicitEDM( )
{
    var builder = new ODataConventionModelBuilder( );
    builder.EntitySet<AwardTitle>( "AwardTitles" );

    return builder.GetEdmModel( );
}

请注意,我只映射了 AwardTitle 类... 而没有映射 AwardEpisode 类。
现在,当我浏览到控制器时,我期望会出现有关未映射 AwardEpisode 的错误。然而,没有错误。实际上,除了检索到 AwardTitle 之外... 还检索到了 AwardEpisode... 而没有任何明确的调用。
这怎么可能???这应该是可能的吗??
我正在使用 Windows 7 上的 ASP.Net Web API 2。

我敢打赌,EDM生成器使用反射递归地创建所有依赖类。也许有一个设置可以告诉模板生成器忽略某个类。 - Ross Bush
这是有意设计成这样的。 - vittore
Vitore,我认为这不是设计上的问题。每次我实现控制器时,除非我使用$expand明确要求它们,否则不会包括依赖类。 - Chris
1个回答

1
默认情况下,ODataConventionModelBuilder会为类型T的原始、复杂和导航属性映射到.EntitySet<TEntityType>(string name) API调用。code如下:
private void MapEntityType(EntityTypeConfiguration entity)
{
    IEnumerable<PropertyInfo> properties = ConventionsHelpers.GetProperties(entity, includeReadOnly: _isQueryCompositionMode);
    foreach (PropertyInfo property in properties)
    {
        bool isCollection;
        StructuralTypeConfiguration mappedType;

        PropertyKind propertyKind = GetPropertyType(property, out isCollection, out mappedType);

        if (propertyKind == PropertyKind.Primitive || propertyKind == PropertyKind.Complex)
        {
            MapStructuralProperty(entity, property, propertyKind, isCollection);
        }
        else
        {
            // don't add this property if the user has already added it.
            if (!entity.NavigationProperties.Where(p => p.Name == property.Name).Any())
            {
                NavigationPropertyConfiguration addedNavigationProperty;
                if (!isCollection)
                {
                    addedNavigationProperty = entity.AddNavigationProperty(property, EdmMultiplicity.ZeroOrOne);
                }
                else
                {
                    addedNavigationProperty = entity.AddNavigationProperty(property, EdmMultiplicity.Many);
                }

                addedNavigationProperty.AddedExplicitly = false;
            }
        }
    }

一个测试用例的示例
public void ModelBuilder_Products()
{
    var modelBuilder = new ODataConventionModelBuilder();
    modelBuilder.EntitySet<Product>("Products");

    var model = modelBuilder.GetEdmModel();

    var product = model.AssertHasEntitySet(entitySetName: "Products", mappedEntityClrType: typeof(Product));
    product.AssertHasPrimitiveProperty(model, "ReleaseDate", EdmPrimitiveTypeKind.DateTime, isNullable: true);
    product.AssertHasComplexProperty(model, "Version", typeof(ProductVersion), isNullable: true);
    product.AssertHasNavigationProperty(model, "Category", typeof(Category), isNullable: true, multiplicity: EdmMultiplicity.ZeroOrOne);

为了改变默认行为,我们可以忽略该属性:
var builder = new ODataConventionModelBuilder();
builder.Entity<AwardTitle>().Ignore(a => a.Episode);
builder.EntitySet<AwardTitle>("AwardTitles");

return builder.GetEdmModel();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接