Khung thực thể - Tên cột không hợp lệ '* _ID "


100

Tôi đã thu hẹp điều này thành một số vấn đề giữa Code First và Database first EF, nhưng tôi không chắc chắn cách khắc phục nó. Tôi sẽ cố gắng nói rõ nhất có thể, nhưng thành thật mà nói, bản thân tôi cũng thiếu một số hiểu biết ở đây. Đây là Khung thực thể 4.4

Tôi kế thừa một dự án trong đó Entity Framework đã được sử dụng, nhưng nhiều tệp thực tế đã bị xóa mà không có cách nào thực sự để quay lại. Tôi đã thêm lại EF (Cơ sở dữ liệu trước) và sao chép thiết lập T4 mà dự án đã được xây dựng xung quanh. Nó tạo ra các phiên bản mã của tất cả các mô hình cơ sở dữ liệu và một tệp mã DBContext.

Nếu chuỗi kết nối của tôi trông giống như một chuỗi kết nối .NET "bình thường", tôi gặp lỗi về cột không hợp lệ. Tên "ProcessState_ID" không tồn tại. ProcessState_ID hoàn toàn không có trong mã cơ sở, nó không có trong tệp EDMX hoặc bất cứ thứ gì. Đây dường như là một số chuyển đổi EF tự động trong truy vấn.

Khi tôi làm cho chuỗi kết nối khớp với mô hình Entity Framework, nó hoạt động tốt.

Bây giờ khi cố gắng khớp mã trước đó với Entity Framework, tôi muốn giữ chuỗi kết nối .NET "bình thường".

Vì vậy, tôi có hai câu hỏi ở đây: 1. Cách tốt để đi từ một chuỗi kết nối bình thường sang một chuỗi kết nối EF trong mã là gì? 2. Có bản sửa lỗi nào khác ở đây mà tôi không thấy để ngăn lỗi tên cột không hợp lệ không?


3
Điều này cũng xảy ra nếu bạn có một tài sản chuyển hướng với chỉ một get accessor:public virtual Person Person { get; }
Safak Gur

Câu trả lời:


90

Kiểm tra xem bạn có bất kỳ ICollections không.

Những gì tôi đã tìm ra là khi bạn có một ICollection tham chiếu đến một bảng và không có cột nào mà nó có thể tìm ra, nó sẽ tạo ra một cột để bạn cố gắng tạo kết nối giữa các bảng. Điều này đặc biệt xảy ra với ICollection và đã khiến tôi "bất lực" khi cố gắng tìm ra nó.


43
Chỉ cần nói rõ về câu trả lời này, vì nó chính xác nhất đối với tình huống của tôi (nhưng tôi không biết nó cho đến khi tôi tìm ra vấn đề của mình). Nếu bạn gặp một số lỗi liên quan đến OtherTable_ID khi bạn đang truy xuất Bảng, hãy chuyển đến mô hình OtherTable của bạn và đảm bảo rằng bạn không có ICollection <Table> trong đó. Nếu không có mối quan hệ được xác định, khung sẽ tự động giả định rằng bạn phải có FK to OtherTable và tạo các thuộc tính bổ sung này trong SQL được tạo.
LUKE

15
EF lãng phí 4 của tôi giờ
Nitin Sawant

2
@NitinSawant Đó là nó? EF lãng phí tôi 4 giờ mỗi ngày với tất cả các bản sao và hồ sơ chưa đính kèm.
Jacob

@LUKE Bình luận của bạn đã cứu tôi. Tôi yêu bạn rất nhiều :)
Amir Hossein Ahmadi

1
@LUKE người hùng EF mà chúng ta cần, không phải người hùng EF mà chúng ta xứng đáng. Tôi mến bạn.
Matthew Young

62

Đây là một mục muộn cho những người (như tôi), những người không hiểu ngay lập tức 2 câu trả lời còn lại.

Vì thế...

EF đang cố gắng ánh xạ tới tên MONG MUỐN từ BẢNG PHỤ HUYNH THAM KHẢO ... và vì ... tên NGOẠI KHÓA đã được "thay đổi hoặc rút ngắn" trong mối quan hệ BẢNG TRẺ EM của cơ sở dữ liệu ... bạn sẽ nhận được thông báo ở trên.

(bản sửa lỗi này có thể khác nhau giữa các phiên bản của EF)

ĐỐI VỚI TÔI VIỆC SỬA CHỮA LÀ:
THÊM thuộc tính "ForeignKey" vào mô hình

public partial class Tour
{
    public Guid Id { get; set; }

    public Guid CategoryId { get; set; }

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

    [StringLength(500)]
    public string Description { get; set; }

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

    [StringLength(500)]
    public string TourUrl { get; set; }

    [StringLength(500)]
    public string ThumbnailUrl { get; set; }

    public bool IsActive { get; set; }

    [Required]
    [StringLength(720)]
    public string UpdatedBy { get; set; }

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

4
Điều này đã làm việc cho tôi. +1 vì là nơi duy nhất tôi tìm thấy câu trả lời này.
Jerry Benson-Montgomery

@Jerry Tôi đã xác định khóa forign. Nhưng nó vẫn tìm kiếm Category_Id. Bạn đã đề cập đến các bản sửa lỗi cho các phiên bản EF khác nhau phải không? tôi đang sử dụng EF 6.0 Cách khắc phục tôi canadopt là gì?
Ajay Aradhya

@ ajay-aradhya Trên thực tế, chính người trả lời ban đầu, tù nhân-zero, đã đưa ra nhận xét về các phiên bản khác nhau của EF.
Jerry Benson-Montgomery

@ JerryBenson-Montgomery đừng bận tâm! tôi đã làm cho nó hoạt động. Đó là ánh xạ 'một đối một' khiến nó tìm kiếm *_ID. Bao gồm cả tham chiếu trở lại hoạt động tốt.
Ajay Aradhya

1
Bạn cũng có thể khắc phục điều này bằng cách thêm một lớp siêu dữ liệu một phần để bạn sẽ không phải sửa lỗi này khi tạo lại. [MetadataType(typeof(MetaData))] public partial class Tour { public class MetaData { [ForeignKey(nameof(TourCategory))] public virtual TourCategory TourCategory { get; set; } } }
Carter Medlin

39

Chúa ơi - sau nhiều giờ cố gắng, cuối cùng tôi cũng hiểu ra điều này.

Tôi đang làm cơ sở dữ liệu EF6 trước tiên và tôi đã tự hỏi về lỗi "cột không xác định mức độ" - nó đang tạo tên cột gạch dưới tên bảng vì một số lý do và cố gắng tìm một cột không tồn tại.

Trong trường hợp của tôi, một trong các bảng của tôi có hai tham chiếu khóa ngoại đến cùng một khóa chính trong bảng khác - giống như sau:

Animals            Owners
=======            ======
AnimalID (PK)      Pet1ID    <- FK to AnimalID
                   Pet2ID    <- also FK to AnimalID

EF đã tạo ra một số tên cột lạ như Owners_AnimalID1Owners_AnimalID2và sau đó tiến hành để phá vỡ chính nó.

Mẹo ở đây là các khóa ngoại khó hiểu này cần phải được đăng ký với EF bằng Fluent API!

Trong ngữ cảnh cơ sở dữ liệu chính của bạn, ghi đè OnModelCreatingphương thức và thay đổi cấu hình thực thể. Tốt hơn là bạn sẽ có một tệp riêng mở rộng EntityConfigurationlớp, nhưng bạn có thể làm điều đó nội tuyến.

Bất kỳ cách nào bạn làm điều đó, bạn sẽ cần thêm một cái gì đó như sau:

public class OwnerConfiguration : EntityTypeConfiguration<Owner>
{
    public OwnerConfiguration()
    {
        HasRequired(x => x.Animals)
            .WithMany(x => x.Owners)  // Or, just .WithMany()
            .HasForeignKey(x => x.Pet1ID);
    }
}

Và cùng với đó, EF sẽ (có thể) bắt đầu hoạt động như bạn mong đợi. Bùng nổ.

Ngoài ra, bạn sẽ gặp lỗi tương tự nếu bạn sử dụng ở trên với một cột nullable - chỉ cần sử dụng .HasOptional()thay vì .HasRequired().


Đây là liên kết đưa tôi vượt qua cái bướu:

https://social.msdn.microsoft.com/Forums/en-US/862abdae-b63f-45f5-8a6c-0bdd6eeabfdb/getting-sqlexception-invalid-column-name-userid-from-ef4-codeonly?forum=adonetefx

Và sau đó, tài liệu API Fluent sẽ trợ giúp, đặc biệt là các ví dụ về khóa ngoại:

http://msdn.microsoft.com/en-us/data/jj591620.aspx

Bạn cũng có thể đặt các cấu hình ở đầu kia của khóa, như được mô tả ở đây:

http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx .

Có một số vấn đề mới mà tôi đang gặp phải, nhưng đó là khoảng cách khái niệm lớn bị thiếu. Hy vọng nó giúp!


1
Cảm ơn rất nhiều .. Tôi đã có cùng một vấn đề.
Sachin Parashar

14

Các giả định:

  • Table
  • OtherTable
  • OtherTable_ID

Bây giờ hãy chọn một trong những cách sau:


A)

Tẩy ICollection<Table>

Nếu bạn gặp một số lỗi liên quan đến OtherTable_IDthời điểm bạn đang truy xuất Table, hãy chuyển đến OtherTablemô hình của bạn và đảm bảo rằng bạn không có lỗi ICollection<Table>trong đó. Nếu không có mối quan hệ được xác định, khung sẽ tự động giả định rằng bạn phải có FK to OtherTable và tạo các thuộc tính bổ sung này trong SQL được tạo.

Tất cả Tín dụng của câu trả lời này thuộc về @LUKE. Câu trả lời trên là bình luận của anh ấy dưới câu trả lời của @cedid. Tôi nghĩ rằng bình luận của anh ấy quá rõ ràng nên tôi đã viết lại nó như một câu trả lời.


B)

  • Thêm OtherTableIdvàoTable

  • Xác định OtherTableIdtrong Tablecơ sở dữ liệu

1
Như một câu trả lời sáng suốt!
Amir Hossein Ahmadi

Câu trả lời này thực sự được lưu lại theo ngày một cách nhanh chóng. và cảm ơn LUKE, tôi đã đọc bình luận của anh ấy. Mặc dù @ rút gọn được câu trả lời ở cuối cùng của chuỗi câu trả lời, nhưng nó thật tuyệt vời và là điều cần thiết nhất khi đối mặt với tình huống này.
Div Tiwari

3

Trong trường hợp của tôi, tôi đã xác định sai khóa chính được tạo thành từ hai khóa ngoại như sau:

HasKey(x => x.FooId);
HasKey(x => x.BarId);

HasRequired(x => x.Foo)
    .WithMany(y => y.Foos);
HasRequired(x => x.Bar);

Lỗi mà tôi gặp phải là "tên cột không hợp lệ Bar_ID".

Chỉ định khóa chính tổng hợp một cách chính xác đã khắc phục sự cố:

HasKey(x => new { x.FooId, x.BarId });

...

3

Đối với tôi, nguyên nhân của hành vi này là do sự cố với ánh xạ được xác định với API Fluent. Tôi có 2 kiểu liên quan, trong đó kiểu A có đối tượng kiểu B tùy chọn và kiểu B có nhiều đối tượng A.

public class A 
{
    
    public int? BId {get; set;}
    public B NavigationToBProperty {get; set;}
}
public class B
{
    
    public List<A> ListOfAProperty {get; set;}
}

Tôi đã xác định ánh xạ với api thông thạo như thế này:

A.HasOptional(p=> p.NavigationToBProperty).WithMany().HasForeignKey(key => key.BId);

Nhưng vấn đề là, loại B đó có thuộc tính điều hướng List<A>, vì vậy kết quả là tôi cóSQLException Invalid column name A_Id

Tôi đã đính kèm Visual Studio Debug vào EF DatabaseContext.Database.Log để xuất cửa sổ SQL ra VS Output-> Debug được tạo

db.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);

Và SQL được tạo có 2 quan hệ từ bảng B -> một quan hệ với id chính xác và quan hệ khác với A_Id

Vấn đề của sự cố là tôi đã không thêm thuộc tính điều B.List<A>hướng này vào ánh xạ.

Vì vậy, đây là cách trong trường hợp của tôi, ánh xạ đúng phải là:

A.HasOptional(p=> p.NavigationToBProperty).WithMany(x => x.ListOfAProperty).HasForeignKey(key => key.BId);

2

Trong trường hợp của tôi, nguyên nhân cho sự cố này là thiếu ràng buộc NGOẠI KHÓA trên cơ sở dữ liệu đã di chuyển. Vì vậy, ICollection ảo hiện có không được tải thành công.


1

Tôi cũng đã gặp vấn đề này và có vẻ như có một vài nguyên nhân khác nhau. Đối với tôi, nó có một thuộc tính id được định nghĩa nhầm thành int thay vì long trong lớp cha có chứa một đối tượng điều hướng. Trường id trong cơ sở dữ liệu được định nghĩa là bigint tương ứng với long trong C #. Điều này không gây ra lỗi thời gian biên dịch nhưng đã gây ra lỗi thời gian chạy tương tự như OP mắc phải:

// Domain model parent object
public class WidgetConfig 
{
    public WidgetConfig(long id, int stateId, long? widgetId)
    {
        Id = id;
        StateId = stateId;
        WidgetId = widgetId;
    }

    private WidgetConfig()
    {
    }

    public long Id { get; set; }

    public int StateId { get; set; }

    // Ensure this type is correct
    public long? WidgetId { get; set; } 

    public virtual Widget Widget { get; set; }
}

// Domain model object
public class Widget
{
    public Widget(long id, string name, string description)
    {
        Id = id;
        Name = name;
        Description = description;
    }

    private Widget()
    {
    }

    public long Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }
}

// EF mapping
public class WidgetConfigMap : EntityTypeConfiguration<WidgetConfig>
{
    public WidgetConfigMap()
    {
        HasKey(x => x.Id);
        ToTable(nameof(WidgetConfig));
        Property(x => x.Id).HasColumnName(nameof(WidgetConfig.Id)).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
        Property(x => x.StateId).HasColumnName(nameof(WidgetConfig.StateId));
        Property(x => x.WidgetId).HasColumnName(nameof(WidgetConfig.WidgetId));
    }
}   

// Service
public class WidgetsService : ServiceBase, IWidgetsService
{
    private IWidgetsRepository _repository;

    public WidgetsService(IWidgetsRepository repository)
    {
        _repository = repository;
    }

    public List<WidgetConfig> ListWithDetails()
    {
        var list = _repository.ListWithDetails();

        return new WidgetConfigMapping().ConvertModelListToDtoList(list).ToList();
    }
}   

// Repository
public class WidgetsRepository: BaseRepository<WidgetConfig, long>, IWidgetsRepository
{
    public WidgetsRepository(Context context)
        : base(context, id => widget => widget.Id == id)
    {
    }

    public IEnumerable<WidgetConfig> ListWithDetails()
    {
        var widgets = Query
            .Include(x => x.State)
            .Include(x => x.Widget);

        return widgets;
    }
}

1

Đối với tôi, vấn đề là tôi đã ánh xạ bảng trong ứng dụng của mình hai lần - một lần qua Code First, một lần qua Database First.

Loại bỏ một trong hai giải quyết vấn đề trong trường hợp của tôi.


1

Đối với tôi, điều đó xảy ra do các vấn đề đa dạng hóa của EF. Đối với các bảng kết thúc bằng "-Status", EF cho rằng số ít là "-Statu". Thay đổi thực thể và tên bảng DB thành "-StatusTypes" đã sửa nó.

Bằng cách này, bạn sẽ không cần đổi tên các mô hình thực thể mỗi khi nó được cập nhật.


0

Nếu bạn có tham chiếu khóa ngoại đến cùng một bảng nhiều lần, thì bạn có thể sử dụng InverseProperty

Một cái gì đó như thế này-

[InverseProperty("MyID1")]
public virtual ICollection<MyTable> set1 { get; set; }
[InverseProperty("MyID2")]
public virtual ICollection<MyTable> set2 { get; set; }

0

Đối với tôi (sử dụng Visual Studio 2017 và mô hình ưu tiên cơ sở dữ liệu trong Entity Framework 6.1.3), sự cố đã biến mất sau khi khởi động lại Visual Studio và xây dựng lại.


Đây không phải là câu trả lời dứt khoát cho câu hỏi vì bạn không giải thích nguyên nhân. Nó nên được đưa vào như một bình luận.
Ibo

0

Trong trường hợp của tôi, dữ liệu phương thức hạt giống của tôi vẫn đang gọi một cột bảng đã bị loại bỏ trong lần di chuyển trước. Kiểm tra kỹ các ánh xạ của bạn nếu bạn đang sử dụng Automapper.


0

Trong trường hợp của tôi, tôi đã có một cơ sở dữ liệu (Database firts). Cảm ơn tất cả các ý kiến ​​ở đây, tôi đã tìm thấy giải pháp của mình:

Các bảng phải có mối quan hệ nhưng tên của các cột cần khác nhau và thêm thuộc tính ForeignKey.

[ForeignKey ("PrestadorId")] công khai ảo AwmPrestadoresServicios Colaboradores {get; bộ; }

Tức là, PRE_ID là PK, nhưng FK trong bảng khác là PRESTADOR_ID, thì nó hoạt động. Cảm ơn tất cả các ý kiến ​​ở đây tôi đã tìm thấy giải pháp của mình. EF hoạt động theo những cách bí ẩn.


0

Nếu bạn gặp sự cố này với thuộc tính điều hướng trên cùng một bảng, bạn sẽ phải thay đổi tên của thuộc tính của chúng tôi.

Ví dụ :

Table : PERSON
Id
AncestorId (with a foreign key which references Id named Parent) 

Bạn sẽ phải thay đổi AncestorIdcho PersonId.

Có vẻ như EF đang cố gắng tạo một khóa ParentIdvì nó không thể tìm thấy bảng có tên là Ancestor ...

CHỈNH SỬA: Đây là bản sửa lỗi cho Cơ sở dữ liệu trước tiên!

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.