简体   繁体   English

OData V4的Web Api无法与HasKey一起使用

[英]Web Api for OData V4 doesn't Work With HasKey

I'm using web api 2.2 for odata v4, and below is the models: 我将Web API 2.2用于odata v4,以下是模型:

[Table("User")]
public partial class User
{
    public User()
    {
        UserRoles = new HashSet<UserRole>();
    }

    [StringLength(50)]
    public string Id { get; set; }

    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

[Table("UserRole")]
public partial class UserRole
{
    [Key]
    [Column(Order = 0)]
    [StringLength(50)]
    public string UserId { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(50)]
    public string RoleName { get; set; }

    public virtual User User { get; set; }
}

and below is the WebApiConfig.cs code: 下面是WebApiConfig.cs代码:

        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<User>("Users");
        builder.EntitySet<UserRole>("UserRoles");            
        config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
        config.AddODataQueryFilter();

Till now, every thing works well. 到现在为止,一切正常。 But, if I remove the [Key] form the UserRole definition. 但是,如果我从用户角色定义中删除了[Key]。 and use the code : 并使用代码:

builder.EntitySet<UserRole>("UserRoles").EntityType.HasKey(r => new { r.UserId, r.RoleName });

The when I query on User, I always get the error that tells UserRoles has no key definition. 当我在User上查询时,我总是得到告诉UserRoles没有键定义的错误。

I have upload the source porject files @ https://cloud.seafile.com/f/bdff340ec3/ Please check the webapiconfig.cs User.cs UserRole.cs and web.config (for database connection string). 我已经上载了源项目文件@ https://cloud.seafile.com/f/bdff340ec3/请检查webapiconfig.cs User.cs UserRole.cs和web.config(用于数据库连接字符串)。 When you access /odata/Users?$expand=UserRoles you will get the error 当您访问/ odata / Users?$ expand = UserRoles时,您将收到错误消息

Just change 只是改变

builder.EntitySet<UserRole>("UserRoles").EntityType.HasKey(r => new { r.UserId, r.RoleName });

To

EntityTypeConfiguration<UserRole> userRoleType=builder.EntitySet<UserRole>("UserRoles").EntityType;
userRoleType.HasKey(p=>p.UserId);
userRoleType.HasKey(p=>p.RoleName);

I have the same problem. 我也有同样的问题。 Here is what I am doing right now, not finished so I do not know if there will be other issues. 这是我现在正在做的事情,尚未完成,所以我不知道是否还会有其他问题。

In my model I changed UserId to Id so OData convention will use it as the key and then in my dbcontext map file I used: 在我的模型中,我将UserId更改为Id,因此OData约定将其用作键,然后在我的dbcontext映射文件中使用:

public class DbLdapMap : EntityTypeConfiguration<DbLdap>
{
    public DbLdapMap()
    {
        ToTable("LDAP");

        //Primary Key
        HasKey(t => t.Id);

        // Properties
        Property(t => t.Id).HasColumnName("UserId");

    }
}

I really want to keep all the database definitions in the Fluent API. 我真的很想将所有数据库定义保留在Fluent API中。

I tried your project, and the odata metadata "/odata/$metadata" seems fine to me. 我尝试了您的项目,对我来说,odata元数据“ / odata / $ metadata”似乎还不错。

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
  <edmx:DataServices>
    <Schema Namespace="WebApplication1.Models.OData" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityType Name="User">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.String" Nullable="false" />
        <Property Name="Name" Type="Edm.String" Nullable="false" />
        <NavigationProperty Name="UserRoles" Type="Collection(WebApplication1.Models.OData.UserRole)" />
      </EntityType>
      <EntityType Name="UserRole">
        <Key>
          <PropertyRef Name="UserId" />
          <PropertyRef Name="RoleName" />
        </Key>
        <Property Name="UserId" Type="Edm.String" Nullable="false" />
        <Property Name="RoleName" Type="Edm.String" Nullable="false" />
        <NavigationProperty Name="User" Type="WebApplication1.Models.OData.User" />
      </EntityType>
    </Schema>
    <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityContainer Name="Container">
        <EntitySet Name="Users" EntityType="WebApplication1.Models.OData.User">
          <NavigationPropertyBinding Path="UserRoles" Target="UserRoles" />
        </EntitySet>
        <EntitySet Name="UserRoles" EntityType="WebApplication1.Models.OData.UserRole">
          <NavigationPropertyBinding Path="User" Target="Users" />
        </EntitySet>
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

The problem is that UserRole has no keys defined in the DB model rather than the OData EDM model. 问题在于UserRole在DB模型而不是OData EDM模型中没有定义键。

If you remove the Key attribute on UserId and RoleName, the DBModelBuilder doesn't know what the keys are. 如果删除UserId和RoleName上的Key属性,则DBModelBuilder不知道键是什么。

So you need to add the following code to Database.OnModelCreating without [Key]: 因此,您需要将以下代码添加到不带[Key]的Database.OnModelCreating中

modelBuilder.Entity<UserRole>()
                .HasKey(r => new { r.UserId, r.RoleName });

What is more, you need to add EnableQuery attribute on the action if you want to support to apply $expand on the result : 此外, 如果要支持对结果应用$ expand,则需要在操作上添加EnableQuery属性

        [EnableQuery]
        public IQueryable<User> GetUsers()
        {
            var db = new Database();
            return db.Users;
        }

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

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