Mã EF Đầu tiên Tên không hợp lệ Tên cột 'Phân biệt đối xử' không có quyền thừa kế


154

Tôi có một bảng trong cơ sở dữ liệu của mình được gọi là SEntries (xem bên dưới câu lệnh CREATE TABLE). Nó có một khóa chính, một vài khóa ngoại và không có gì đặc biệt về nó. Tôi có nhiều bảng trong cơ sở dữ liệu của mình tương tự như bảng đó, nhưng vì một số lý do, bảng này đã kết thúc với cột "Phân biệt đối xử" trên Lớp Proxy của EF.

Đây là cách lớp được khai báo trong C #:

public class SEntry
{
    public long SEntryId { get; set; }

    public long OriginatorId { get; set; }
    public DateTime DatePosted { get; set; }
    public string Message { get; set; }
    public byte DataEntrySource { get; set; }
    public string SourceLink { get; set; }
    public int SourceAppId { get; set; }
    public int? LocationId { get; set; }
    public long? ActivityId { get; set; }
    public short OriginatorObjectTypeId { get; set; }
}

public class EMData : DbContext
{
    public DbSet<SEntry> SEntries { get; set; }
            ...
    }

Khi tôi cố gắng thêm một hàng mới vào bảng đó, tôi gặp lỗi:

System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.

Vấn đề này chỉ xảy ra nếu bạn đang kế thừa lớp C # của mình từ một lớp khác, nhưng SEntry không được thừa hưởng từ bất cứ điều gì (như bạn có thể thấy ở trên).

Ngoài ra, một khi tôi nhận được mẹo công cụ về trình gỡ lỗi khi tôi di chuột qua đối tượng EMData cho thuộc tính SEntries, nó sẽ hiển thị:

base {System.Data.Entity.Infrastructure.DbQuery<EM.SEntry>} = {SELECT 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[SEntryId] AS [SEntryId], 
[Extent1].[OriginatorId] AS [OriginatorId], 
[Extent1].[DatePosted] AS [DatePosted], 
[Extent1].[Message] AS [Message], 
[Extent1].[DataEntrySource] AS [DataE...

Bất kỳ đề xuất hoặc ý tưởng để đi đến tận cùng của vấn đề này? Tôi đã thử đổi tên bảng, khóa chính và một vài thứ khác, nhưng không có gì hoạt động.

Bảng SQL:

CREATE TABLE [dbo].[SEntries](
[SEntryId] [bigint] IDENTITY(1125899906842624,1) NOT NULL,
[OriginatorId] [bigint] NOT NULL,
[DatePosted] [datetime] NOT NULL,
[Message] [nvarchar](500) NOT NULL,
[DataEntrySource] [tinyint] NOT NULL,
[SourceLink] [nvarchar](100) NULL,
[SourceAppId] [int] NOT NULL,
[LocationId] [int] NULL,
[ActivityId] [bigint] NULL,
[OriginatorObjectTypeId] [smallint] NOT NULL,
CONSTRAINT [PK_SEntries] PRIMARY KEY CLUSTERED 
(
[SEntryId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_ObjectTypes] FOREIGN KEY([OriginatorObjectTypeId])
REFERENCES [dbo].[ObjectTypes] ([ObjectTypeId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_ObjectTypes]
GO

ALTER TABLE [dbo].[SEntries]  WITH CHECK ADD  CONSTRAINT [FK_SEntries_SourceApps] FOREIGN KEY([SourceAppId])
REFERENCES [dbo].[SourceApps] ([SourceAppId])
GO

ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_SourceApps]
GO

16
Đối với người tiếp theo sẽ dành thời gian cố gắng tìm hiểu điều này, điều xảy ra là ở một nơi khác trên mã, tôi có một lớp được thừa hưởng từ SEntry, mặc dù đó không phải là một lớp sẽ được lưu trữ trên DB . Vì vậy, tất cả những gì tôi cần làm là thêm [NotMapped] làm thuộc tính của lớp đó!
Marcelo Calbucci

Tôi gặp lỗi này nếu tôi không đặt [NotMapped] trên lớp ApplicationUser trong Identitymodel.cs
Heemanshu Bhalla

Câu trả lời:


319

Hóa ra Entity Framework sẽ cho rằng bất kỳ lớp nào kế thừa từ lớp POCO được ánh xạ tới bảng trên cơ sở dữ liệu đều yêu cầu cột Discriminator, ngay cả khi lớp dẫn xuất sẽ không được lưu vào DB.

Giải pháp khá đơn giản và bạn chỉ cần thêm [NotMapped]như một thuộc tính của lớp dẫn xuất.

Thí dụ:

class Person
{
    public string Name { get; set; }
}

[NotMapped]
class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}

Bây giờ, ngay cả khi bạn ánh xạ lớp Person vào bảng Person trên cơ sở dữ liệu, cột "Discriminator" sẽ không được tạo vì lớp dẫn xuất có [NotMapped].

Là một mẹo bổ sung, bạn có thể sử dụng [NotMapped]các thuộc tính mà bạn không muốn ánh xạ tới một trường trên DB.


7
Được rồi, cuộc sống của tôi đã trôi qua 3 tiếng đồng hồ; (nhưng tyvm đều giống nhau vẫn sẽ cố gắng và vẽ chúng trong ... rất khó hiểu.
rism

12
Nếu bạn không tìm thấy [NotMapped], vui lòng thêm một tham chiếu đến: "System.ComponentModel.DataAnnotations" vào dự án từ "Khung hội".
XandrUu

9
sử dụng System.ComponentModel.DataAnnotations.Schema;
ygaradon

6
nhưng trong trường hợp của tôi, tôi đã kế thừa một lớp để thêm cột trong bảng db bằng cách sử dụng lớp con. Vì vậy, tôi không thể sử dụng thuộc tính notmaps này để làm cho nó hoạt động. Điều gì nên là giải pháp của tôi trong trường hợp này?
sohaib đã nói đùa

4
trong trường hợp của tôi thêm không ánh xạ đã không giúp đỡ. tôi chưa từng thấy trong tất cả các chế độ xem
Heemanshu Bhalla

44

Đây là cú pháp API trôi chảy.

http://bloss.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-fluent-api-samples.aspx

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { 
        get {
            return this.FirstName + " " + this.LastName;
        }
    }
}

class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}


protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // ignore a type that is not mapped to a database table
    modelBuilder.Ignore<PersonViewModel>();

    // ignore a property that is not mapped to a database column
    modelBuilder.Entity<Person>()
        .Ignore(p => p.FullName);

}

Sẽ không tốt hơn nếu chỉ thêm [NotMapped]thuộc tính?
Keith

1
@ Trả lời câu trả lời của tôi là làm thế nào để bỏ qua một cột bằng API Fluent, không sử dụng các thuộc tính như [NotMapped]
Walter Stabosz

1
Keith đây là câu trả lời ưa thích mà tôi nghĩ bởi vì hiện đang chuyển sang một tiêu chuẩn đầu tiên về mã và câu trả lời của Walter phù hợp hơn cho kịch bản này, đặc biệt nếu bạn kết thúc việc sử dụng chuyển đổi db.
Tahir Khalid

Trường hợp bạn gặp vấn đề ngược lại (tức là lớp ràng buộc EF và kế thừa từ lớp POCO) thì đây là cách duy nhất tôi có thể làm cho nó hoạt động mà không làm ô nhiễm mô hình dữ liệu với EF.
Paul Michaels

8

Tôi vừa gặp phải điều này và vấn đề của tôi là do có hai thực thể cả hai cùng System.ComponentModel.DataAnnotations.Schema.TableAttributetham chiếu đến cùng một bảng.

ví dụ:

[Table("foo")]
public class foo
{
    // some stuff here
}

[Table("foo")]
public class fooExtended
{
    // more stuff here
}

thay đổi cái thứ hai từ foođể foo_extendedsửa cái này cho tôi và tôi hiện đang sử dụng Table Per Type (TPT)


Điều này không hiệu quả với tôi:The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy
James Reategui

Cảm ơn, đã giúp tôi, có cùng một vấn đề khi sử dụng API trôi chảy: var entity = modelBuilder.Entity<EntityObject>().ToTable("ENTITY_TABLE")và sau đó, một dòng khác sử dụng giống EntityObjecthoặc tương tự ENTITY_TABLE.
Mathijs Flietstra

4

Một kịch bản khác xảy ra là khi bạn có một lớp cơ sở và một hoặc nhiều lớp con, trong đó ít nhất một trong các lớp con giới thiệu các thuộc tính bổ sung:

class Folder {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

// Adds no props, but comes from a different view in the db to Folder:
class SomeKindOfFolder: Folder {
}

// Adds some props, but comes from a different view in the db to Folder:
class AnotherKindOfFolder: Folder {
  public string FolderAttributes { get; set; }
}

Nếu chúng được ánh xạ DbContextnhư dưới đây, lỗi "'Tên cột không hợp lệ' Phân biệt đối xử '" xảy ra khi bất kỳ loại nào dựa trên Folderloại cơ sở được truy cập:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<Folder>().ToTable("All_Folders");
  modelBuilder.Entity<SomeKindOfFolder>().ToTable("Some_Kind_Of_Folders");
  modelBuilder.Entity<AnotherKindOfFolder>().ToTable("Another_Kind_Of_Folders");
}

Tôi thấy rằng để khắc phục sự cố, chúng tôi trích xuất các đạo cụ của Foldermột lớp cơ sở (không được ánh xạ OnModelCreating()) như vậy - OnModelCreatingnên không thay đổi:

class FolderBase {
  [key]
  public string Id { get; set; }

  public string Name { get; set; }
}

class Folder: FolderBase {
}

class SomeKindOfFolder: FolderBase {
}

class AnotherKindOfFolder: FolderBase {
  public string FolderAttributes { get; set; }
}

Điều này giúp loại bỏ vấn đề, nhưng tôi không biết tại sao!


cảm ơn, Meataxe - điều đó làm tôi mất một hoặc hai giờ, nhưng điều tồi tệ nhất là, tôi phải có vấn đề này trước đây, bởi vì tôi đã thiết lập tất cả các lớp cơ sở. Dumber tôi một năm sau đó nói, "Này, có vẻ như lớp cơ sở này không làm gì cả. Tôi nghĩ tôi sẽ loại bỏ nó ..." Và đã có một giờ trong cuộc đời tôi sẽ không bao giờ quay trở lại. TẠI SAO NÀY YÊU CẦU? Tôi ước tôi hiểu rõ hơn về EF.
Wellspring

2

Tôi gặp lỗi trong một tình huống khác, và đây là vấn đề và giải pháp:

Tôi có 2 lớp xuất phát từ cùng một lớp cơ sở có tên LevledItem:

public partial class Team : LeveledItem
{
   //Everything is ok here!
}
public partial class Story : LeveledItem
{
   //Everything is ok here!
}

Nhưng trong DbContext của họ, tôi đã sao chép một số mã nhưng quên thay đổi một trong các tên lớp:

public class MFCTeamDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Team));
    }

public class ProductBacklogDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Other codes here
        modelBuilder.Entity<LeveledItem>()
            .Map<Team>(m => m.Requires("Type").HasValue(ItemType.Story));
    }

Có, Bản đồ thứ hai <Đội> phải là Bản đồ <Câu chuyện>. Và tôi mất nửa ngày để tìm ra nó!


2

Tôi đã có một vấn đề tương tự, không chính xác các điều kiện tương tự và sau đó tôi thấy bài đăng này . Hy vọng nó sẽ giúp được ai đó. Rõ ràng tôi đã sử dụng một trong các mô hình thực thể EF của mình một lớp cơ sở cho một loại không được chỉ định là một bộ db trong dbcontext của tôi. Để khắc phục vấn đề này, tôi đã phải tạo một lớp cơ sở có tất cả các thuộc tính chung cho hai loại và kế thừa từ lớp cơ sở mới trong số hai loại.

Thí dụ:

//Bad Flow
    //class defined in dbcontext as a dbset
    public class Customer{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //class not defined in dbcontext as a dbset
    public class DuplicateCustomer:Customer{ 
       public object DuplicateId {get; set;}
    }


    //Good/Correct flow*
    //Common base class
    public class CustomerBase{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //entity model referenced in dbcontext as a dbset
    public class Customer: CustomerBase{

    }

    //entity model not referenced in dbcontext as a dbset
    public class DuplicateCustomer:CustomerBase{

       public object DuplicateId {get; set;}

    }

1

lỗi này xảy ra với tôi vì tôi đã làm như sau

  1. Tôi đã thay đổi tên cột của bảng trong cơ sở dữ liệu
  2. (Tôi đã không sử dụng Update Model from database trong Edmx) Tôi đã đổi tên thủ công Tên thuộc tính để khớp với thay đổi trong lược đồ cơ sở dữ liệu
  3. Tôi đã thực hiện một số tái cấu trúc để thay đổi tên của thuộc tính trong lớp giống với lược đồ và mô hình cơ sở dữ liệu trong Edmx

Mặc dù tất cả những điều này, tôi đã nhận được lỗi này

vì thế what to do

  1. Tôi đã xóa mô hình từ Edmx
  2. Nhấp chuột phải và Update Model from database

điều này sẽ tạo lại mô hình, và khung thực thể will không give you this error

hy vọng điều này sẽ giúp bạn


1

Q cũ, nhưng đối với hậu thế ... nó cũng xảy ra (.NET Core 2.1) nếu bạn có thuộc tính điều hướng tự tham chiếu ("Cha mẹ" hoặc "Trẻ em" cùng loại) nhưng tên thuộc tính Id không phải là gì EF mong đợi. Đó là, tôi có một thuộc tính "Id" trong lớp được gọi WorkflowBasevà nó có một loạt các bước con liên quan, cũng thuộc loại WorkflowBasevà nó cố gắng liên kết chúng với "WorkflowBaseId" không tồn tại (tên i giả sử nó thích như một mặc định tự nhiên / thông thường). Tôi phải cấu hình một cách rõ ràng sử dụng HasMany(), WithOne()HasConstraintName()để cho nó làm thế nào để đi qua. Nhưng tôi đã dành vài giờ để nghĩ rằng vấn đề nằm ở việc 'ánh xạ' khóa chính của đối tượng, mà tôi đã cố gắng khắc phục một loạt các cách khác nhau nhưng có lẽ nó luôn hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.