Entity Framework - ошибка: основной конец этой ассоциации должен быть явно настроен - PullRequest
1 голос
/ 27 марта 2020

У меня есть проект, построенный на основе ASP. NET MVC 5. Я использую Entity Framework 6.2 для доступа к данным из моей базы данных.

У меня есть следующие две модели

public class Entity<T> where T : struct
{
    [Key]
    public T Id { get; set; }
}

public class User : Entity<int>
{
    public string FirstName { get; set; }

    public int CategoryId { get; set; }
    // more properties removed for the sake of simplicity

    public virtual Category Category { get; set; }
}

public class Category : Entity<int>
{
    public string Name { get; set; }
}

Вот как я обращаюсь к пользователю из контекста базы данных.

User user = await DbContext.Users.FirstAsync(10);

Однако я получаю следующее неожиданное исключение.

Невозможно определить основной конец ассоциации между типами «Категория» и «Пользователь». Основной конец этой ассоциации должен быть явно сконфигурирован с использованием либо API-интерфейса, поддерживающего отношения, либо аннотаций данных.

Я попытался добавить атрибут [ForeignKey] к свойству Category, но это тоже не сработало:

[ForeignKey("CategoryId")]
public virtual Category Category { get; set; }

Я также пытался добавить атрибут InverseProperty

[ForeignKey("CategoryId")]
[InverseProperty("Id")]
public virtual Category Category { get; set; }

, но аннотация обратного свойства выдает следующую ошибку:

Свойство Id не может быть настроен как свойство навигации. Свойство должно быть допустимым типом сущности, а свойство должно иметь неабстрактный метод получения и установки. Для свойств коллекции тип должен реализовывать ICollection, где T является допустимым типом сущности.

Что может быть причиной этой проблемы? Как я могу это исправить?

1 Ответ

0 голосов
/ 27 марта 2020

Я не могу воспроизвести (EF 6.4):

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace Ef6Test
{
    public class Entity<T> where T : struct
    {
        [Key]
        public T Id { get; set; }
    }

    public class User : Entity<int>
    {
        public string FirstName { get; set; }

        public int CategoryId { get; set; }
        // more properties removed for the sake of simplicity

        public virtual Category Category { get; set; }
    }

    public class Category : Entity<int>
    {
        public string Name { get; set; }
    }

    public class Db : DbContext
    {
        public Db(string constr) : base(constr)
        { }

        public DbSet<User> Users { get; set; }
        public DbSet<Category> Categories { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            var constr = "server=localhost;database=ef6test;integrated security=true";
            using var db = new Db(constr);
            db.Database.Delete();
            db.Database.Log = msg => Console.WriteLine(msg); 
            db.Database.Initialize(true);

            var u = new User();
            u.Category = new Category();

            db.Users.Add(u);
            db.SaveChanges();

            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}

выходы

Opened connection at 3/26/2020 5:57:48 PM -05:00

Started transaction at 3/26/2020 5:57:48 PM -05:00

CREATE TABLE [dbo].[Categories] (
    [Id] [int] NOT NULL IDENTITY,
    [Name] [nvarchar](max),
    CONSTRAINT [PK_dbo.Categories] PRIMARY KEY ([Id])
)


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 15 ms with result: -1



CREATE TABLE [dbo].[Users] (
    [Id] [int] NOT NULL IDENTITY,
    [FirstName] [nvarchar](max),
    [CategoryId] [int] NOT NULL,
    CONSTRAINT [PK_dbo.Users] PRIMARY KEY ([Id])
)


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 8 ms with result: -1



CREATE INDEX [IX_CategoryId] ON [dbo].[Users]([CategoryId])


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 7 ms with result: -1



ALTER TABLE [dbo].[Users] ADD CONSTRAINT [FK_dbo.Users_dbo.Categories_CategoryId] FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[Categories] ([Id]) ON DELETE CASCADE


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 9 ms with result: -1



CREATE TABLE [dbo].[__MigrationHistory] (
    [MigrationId] [nvarchar](150) NOT NULL,
    [ContextKey] [nvarchar](300) NOT NULL,
    [Model] [varbinary](max) NOT NULL,
    [ProductVersion] [nvarchar](32) NOT NULL,
    CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
)


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 8 ms with result: -1



INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'202003262257478_InitialCreate', N'Ef6Test.Db',  0x1F...
-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 9 ms with result: 1



Committed transaction at 3/26/2020 5:57:48 PM -05:00

Opened connection at 3/26/2020 5:57:48 PM -05:00

Started transaction at 3/26/2020 5:57:48 PM -05:00

INSERT [dbo].[Categories]([Name])
VALUES (NULL)
SELECT [Id]
FROM [dbo].[Categories]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()


-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 10 ms with result: SqlDataReader



INSERT [dbo].[Users]([FirstName], [CategoryId])
VALUES (NULL, @0)
SELECT [Id]
FROM [dbo].[Users]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()


-- @0: '1' (Type = Int32)

-- Executing at 3/26/2020 5:57:48 PM -05:00

-- Completed in 20 ms with result: SqlDataReader



Committed transaction at 3/26/2020 5:57:48 PM -05:00

Closed connection at 3/26/2020 5:57:48 PM -05:00

Hit any key to exit
...