/ / Web Api dla OData V4 nie działa z HasKey - c #, odata, asp.net-web-api2, odata-v4

Web Api dla OData V4 nie działa z HasKey - c #, odata, asp.net-web-api2, odata-v4

Używam interfejsu API 2.2 dla odata v4, a poniżej są modele:

[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; }
}

a poniżej znajduje się kod WebApiConfig.cs:

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

Do tej pory wszystko działa dobrze. Ale jeśli usunę [Klucz] z definicji UserRole. i użyj kodu:

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

Kiedy pytam użytkownika, zawsze pojawia się błąd informujący, że UserRoles nie ma definicji klucza.

Przesłałem źródłowe pliki porject @ https://cloud.seafile.com/f/bdff340ec3/ Sprawdź pliki webapiconfig.cs User.cs UserRole.cs i web.config (parametry połączenia z bazą danych). Gdy uzyskasz dostęp do / odata / Users? $ Expand = UserRoles otrzymasz błąd

Odpowiedzi:

2 dla odpowiedzi № 1

Po prostu zmień

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

Do

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

1 dla odpowiedzi nr 2

Mam ten sam problem. Oto, co robię teraz, nie dokończono, więc nie wiem, czy pojawią się inne problemy.

W moim modelu zmieniłem identyfikator użytkownika na identyfikator, więc konwencja OData użyje go jako klucza, a następnie w pliku mapy kontekstu dbcontext użyłem:

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

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

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

}
}

Naprawdę chcę zachować wszystkie definicje baz danych w płynnym interfejsie API.


0 dla odpowiedzi № 3

Wypróbowałem Twój projekt, a metadane odata „/ odata / $ metadata” wydają mi się w porządku.

<?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>

Problem polega na tym, że UserRole nie ma zdefiniowanych kluczy w modelu DB zamiast modelu OData EDM.

Jeśli usuniesz atrybut Key na UserId i RoleName, DBModelBuilder nie będzie wiedział, jakie są klucze.

Musisz więc dodać następujący kod do Database.OnModelCreating bez [klucza]:

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

Co więcej, musisz dodaj atrybut EnableQuery do akcji, jeśli chcesz wesprzeć zastosowanie $ expand do wyniku:

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