2016-04-13 19 views
6

sử dụng EF 7: 1.0.0-rc1 kết,Entity Framework 7: Tạo không hợp lệ Cột Tên

Tôi đang gặp rắc rối với EF tạo ra các truy vấn đúng cách, sử dụng cơ sở dữ liệu tiếp cận đầu tiên - sử dụng giàn giáo ef để tạo một số tính chất mô hình được liệt kê trong DbContext - như các bảng có chứa một số lượng lớn các cột tôi chỉ cần một vài làm việc cho WebAPI để họ được cột ánh xạ

tôi có 3 đối tượng, thương hiệu, sự kiện và phiên

Thương hiệu chứa nhiều Sự kiện và Sự kiện chứa nhiều Phiên

mô hình của tôi:

[Table("tblBranding")] 
public class Brand 
{ 
    [Key] 
    [Column("brandingId")] 
    public int BrandId { get; set; } 
    [Column("BrandingActive")] 
    public bool Active { get; set; } 
    [JsonIgnore] 
    [Column("DeadBrand")]   
    public bool DeadBrand { get; set; } 
    [Column("BrandingSiteTitle")] 
    public string Name { get; set; } 

    //navigation properties 
    public virtual ICollection<Event> Events { get; set; } 
} 

[Table("tblEvents")] 
public class Event 
{   
    public int EventId { get; set; } 
    [Column("eventActive")] 
    public bool Active { get; set; } 
    [Column("eventName")] 
    public string Name { get; set; }   
    public DateTime EventCloseDate {get;set;}   
    public int PaxAllocationLimit { get; set; } 

    //navigation properties    
    [JsonIgnore]   
    [Column("brandingId")] 

    public virtual int BrandId { get; set; } 
    [JsonIgnore] 
    [ForeignKey("BrandId")] 
    public virtual Brand Brand { get; set; } 
    public virtual ICollection<Session> Sessions { get; set; } 
} 

[Table("tblEventsDates")] 
public class Session 
{  
    [Column("EventDateID")] 
    public int SessionId { get; set; } 
    [Column("EventDateName")] 
    public string Name { get; set; }    
    [Column("EventDate")] 
    public DateTime SessionDate { get; set; }   
    [Column("EventDateTime")] 
    public DateTime SessionTime { get; set; } 
    [Column("EventDateMinutes")] 
    public decimal? SessionDurationInMinutes { get; set; } 
    [Column("EventDateArrival")] 
    public DateTime? ArrivalTime { get; set; } 
    [Column("EventCapacity")] 
    public int SessionCapacity { get; set; } 

    //navigation properties   
    [JsonIgnore]   
    public virtual int EventId { get; set; } 
    [JsonIgnore]   
    public virtual Event Event { get; set; }    
} 

My DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{  
    modelBuilder.Entity<Event>() 
     .HasOne(e => e.Brand) 
     .WithMany(b => b.Events).HasForeignKey(e=>e.BrandId); 

    modelBuilder.Entity<Event>() 
     .HasMany(s => s.Sessions) 
     .WithOne(e => e.Event).HasForeignKey(s => s.EventId); 

    modelBuilder.Entity<Event>(entity=> { 
     entity.Property(e => e.EventId).HasColumnName("EventID"); 
     entity.HasKey(e => new{ e.EventId, e.EventCloseDate}); 
     entity.HasIndex(e => e.EventId).HasName("For Full Text Indexing").IsUnique(); 
     entity.Property(e => e.Active).HasDefaultValue(false); 
     entity.Property(e => e.EventCloseDate) 
      .HasColumnType("datetime") 
      .HasDefaultValueSql("'1/1/2038'"); 
     entity.Property(e => e.Name).HasMaxLength(1024); 
     entity.Property(e => e.PaxAllocationLimit).HasDefaultValue(10000); 
    }); 

    modelBuilder.Entity<Brand>(entity => { 
     entity.HasKey(e => e.BrandId);     

     entity.Property(e => e.Active).HasDefaultValue(false);    

     entity.Property(e => e.Name) 
      .IsRequired() 
      .HasMaxLength(150) 
      .HasColumnType("varchar");     
    }); 

    modelBuilder.Entity<Session>(entity => { 
     entity.HasKey(e => e.SessionId); 

     entity.Property(e=>e.Name) 
      .HasMaxLength(250) 
      .HasColumnType("varchar") 
      .HasDefaultValue(""); 

     entity.Property(e => e.SessionDurationInMinutes) 
      .HasColumnType("numeric") 
      .HasDefaultValue(0m);     
     }); 
    } 

    public virtual DbSet<Brand> Brands { get; set; } 
    public virtual DbSet<Event> Events { get; set; }   
    public virtual DbSet<Session> Sessions { get; set; } 
} 

Tôi đang sử dụng các dự án như một WebAPI, khi tôi gọi lên Brands, nó tạo ra các SQL sau:

SELECT [e].[brandingId], [e].[BrandingActive], [e].[DeadBrand], [e].[BrandingSiteTitle] 
FROM [tblBranding] AS [e] 
WHERE [e].[BrandingActive] = 1 
ORDER BY [e].[BrandingSiteTitle], [e].[brandingId] 
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (75ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] 
SELECT [t].[EventId], [t].[EventCloseDate], [t].[eventActive], [t].[brandingId], [t].[EventId1], [t].[eventName], [t].[PaxAllocationLimit] 
FROM [tblEvents] AS [t] 
INNER JOIN (
    SELECT DISTINCT [e].[BrandingSiteTitle], [e].[brandingId] 
    FROM [tblBranding] AS [e] 
    WHERE [e].[BrandingActive] = 1 
) AS [e] ON [t].[brandingId] = [e].[brandingId] 
ORDER BY [e].[BrandingSiteTitle], [e].[brandingId] 

trong đó [t]. [EventId1] tên cột không hợp lệ lưu ý rằng nếu tôi nhận xét mã sau trong DbContext - lỗi này biến mất và truy vấn được tạo chính xác :

modelBuilder.Entity<Event>() 
      .HasMany(s => s.Sessions) 
      .WithOne(e => e.Event).HasForeignKey(s => s.EventId); 

Tôi đã thử thêm [ForeignKey], [InverseProperty] thuộc tính trong khi 'loay hoay' - đó dường như không tạo sự khác biệt

Tôi cũng đã cố gắng thêm tên cột một cách rõ ràng như đã đề cập here

Tôi không chắc còn phải thử cái gì khác - nó chỉ bắt đầu xảy ra khi tôi xác định mối quan hệ với Phiên trong FluidUI - đề xuất?

+0

nếu bạn thêm '.ForSqlServerHasConstraintName ("EventId") 'sau' .HasForeignKey (s => s.EventId)' nó thay đổi bất cứ điều gì? – Thomas

+0

vẫn tạo tên cột không hợp lệ sau khi thêm ràng buộc - được kiểm tra bằng cách thêm vào cả hai mối quan hệ với Nhãn hiệu và Phiên – Danish

+0

Âm thanh ngu ngốc nhưng tôi phải đối mặt với vấn đề này sau khi Resharper tái cấu trúc tên bảng và tôi đã không nhận thấy nó. Đổi tên 'ProductCategory' thành' ProductCategories' và Resharper được cấu trúc lại '.ToTable (" ProductCategory ")' thành '.ToTable (" ProductCategories ")' – guneysus

Trả lời

3

Just for fun. hãy thử tạo cơ sở dữ liệu này. Tôi loại bỏ rất nhiều "lộn xộn" EF giống như ASP.NET MVC dựa trên khái niệm về quy ước về cấu hình.

Bạn đã thực hiện cấu hình tối đa 2 lần (thuộc tính và/hoặc FluentApi), trong khi thực tế bạn có thể đã thực hiện nó 0 lần.

Dưới đây là một số quy tắc cơ sở về quy ước (quy ước không phân biệt chữ hoa chữ thường để kích hoạt).

  • Để thực hiện một chính (key aka tiểu học), bạn phải đặt tên cho nó, hoặc Id hoặc [classname] Id
  • Để thực hiện một khóa ngoại bạn đặt tên cho nó [foreighClassName (Parta)] Id (bạn không cần điều này nếu Thay vào đó, bạn thêm tiếp theo (và ofc bạn có thể có cả hai cùng một lúc nhưng sau đó tên phải giống nhau (partA)
  • Để truy cập đối tượng "cơ thể" nước ngoài, bạn chỉ cần thêm thuộc tính kiểu này public Brand Brand { get; set; } , tên không quan trọng nếu chỉ có một "liên kết".
  • Về mặt chính, bạn có thể muốn sử dụng một số loại bộ sưu tập để bọc tất cả trẻ em và có public ICollection<Event> Events { get; set; } là con đường để đi. Người ta có thể hỏi những gì về IEnumerable hoặc IList (suy nghĩ về nó theo cách này, IEnumerable không thể làm .Add() vì vậy nó là nhiều hơn hoặc ít hơn chỉ đọc. thứ đó là không thể dịch để SQL. để ở giữa chúng ta có ICollection.

Khi bạn sử dụng các từ khóa ảo? Vâng trong EF7 bạn không sử dụng nó, vì nó cho phép tải lười biếng, và EF7 không có (chưa) và chúng tôi không biết liệu họ có thêm nó hay không. Github EF7 feature request lacking lazyload

Tại sao tôi xóa các thuộc tính [JsonIgnore]? cho khách hàng. Tạo một DTO thích hợp (thường được gọi là một mô hình trong ASP.NET MVC)

Hãy nhớ di chuyển, và (để giải trí) thử trước mà không có bất kỳ yêu cầu "hardcoded" nào trong FluentAPI và xem mã di chuyển bạn sẽ thấy PK/FK được thực hiện, chỉ số và một số bobs và chân khác được thêm vào cho bạn.

public class Brand 
{ 
    public int Id { get; set; } 
    public bool Active { get; set; } 
    public bool DeadBrand { get; set; } 
    public string Name { get; set; } 

    //navigation properties 
    public ICollection<Event> Events { get; set; } 
} 

public class Event 
{   
    public int Id { get; set; } 
    public bool Active { get; set; } 
    public string Name { get; set; }   
    public DateTime EventCloseDate {get;set;}   
    public int PaxAllocationLimit { get; set; } 

    //navigation properties    
    public Brand Brand { get; set; } 
    public ICollection<Session> Sessions { get; set; } 
} 

public class Session 
{  
    public int Id { get; set; } 
    public string Name { get; set; } 
    //Datetime contains date and time   
    public DateTime Time { get; set; } 
    //TimeSpan is for duration, allowing access to seconds, minutes, hours etc. 
    public TimeSpan Duration { get; set; } 
    public DateTime? ArrivalTime { get; set; } 
    public int SessionCapacity { get; set; } 

    //navigation properties   
    public Event Event { get; set; }    
} 

lớp Context

class DbContex{ 

    public virtual DbSet<Brand> Brands { get; set; } 
    public virtual DbSet<Event> Events { get; set; }   
    public virtual DbSet<Session> Sessions { get; set; } 

    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    {  
    //Personally I would not have many requirements in the database unless I    
    //was completely sure it had to be that way. 
    //They will ALWAYS bite you in the ass in the long run. 

     modelBuilder.Entity<Event>(entity=> { 
      entity.Property(e => e.Active).HasDefaultValue(false); 
      entity.Property(e => e.EventCloseDate) 
       .HasColumnType("datetime") 
       .HasDefaultValueSql("'1/1/2038'"); 
      entity.Property(e => e.Name).HasMaxLength(1024); 
      entity.Property(e => e.PaxAllocationLimit).HasDefaultValue(10000); 
     }); 

     modelBuilder.Entity<Brand>(entity => { 
      entity.Property(e => e.Active).HasDefaultValue(false);  
      entity.Property(e => e.Name) 
       .IsRequired() 
       .HasMaxLength(150) 
       .HasColumnType("varchar");     
     }); 

     modelBuilder.Entity<Session>(entity => { 
      entity.Property(e=>e.Name) 
       .HasMaxLength(250) 
       .HasColumnType("varchar") 
       .HasDefaultValue("");  
      entity.Property(e => e.SessionDurationInMinutes) 
       .HasColumnType("numeric") 
       .HasDefaultValue(0m);     
      }); 
     } 
    } 
} 
+0

Cảm ơn bạn đã giải thích chi tiết, cho các yêu cầu DB không may tôi bị mắc kẹt với một cơ sở dữ liệu hiện có mà rất nhiều ứng dụng khác sử dụng - vì vậy tôi chỉ cần thêm những gì từ những gì giàn giáo đã cho tôi - cảm ơn những lời khuyên về DTO, trong trường hợp này Tuy nhiên tôi không nghĩ rằng tôi sẽ cần nó, như các mô hình ở đây được viết bằng tay và đã được giảm xuống đại diện bảng, không phải là bảng đầy đủ - cảm ơn thời gian của bạn! – Danish

+1

Mô hình Cơ sở dữ liệu/Thực thể thường được viết, nó được gọi là Mã khung thực thể đầu tiên (nghĩa là bạn tạo các đối tượng mô hình thực thể (DTO ish)) và di chuyển chúng vào cơ sở dữ liệu. Nếu bạn thực hiện thay đổi thì bạn phải thêm di chuyển mới để đảm bảo rằng db được đồng bộ hóa với các mô hình. Tôi sẽ không khuyên bạn nên sử dụng EF 7 (Core), cho các mục đích khác so với thử nghiệm tại nó chưa được phát hành và sẽ nhận được một cập nhật khá sớm trong RC 2 (ef 7 đổi tên thành lõi, thay đổi tất cả các không gian tên, tăng tốc lớn và dnu/dnx thay đổi đối với dotnet) và một số thay đổi bổ sung trong bản phát hành Cuối cùng. –

+0

Lộ trình: https://github.com/aspnet/Home/wiki/Roadmap Tốc độ: https://blogs.msdn.microsoft.com/dotnet/2015/11/18/entity-framework-7-rc1-available/ CLI mới: http://dotnet.github.io/getting-started/ –

1

Trả lời câu hỏi của riêng tôi - nó có vẻ như nó có thể là một lỗi trong EF 7 1.0.0-RC1

trong các thuộc tính thực thể cho tổ chức sự kiện trong DbContext

modelBuilder.Entity<Event>(entity=> { 
    entity.Property(e => e.EventId).HasColumnName("EventID"); 
    entity.HasKey(e => new{ e.EventId, e.EventCloseDate}); 
    entity.HasIndex(e => e.EventId).HasName("For Full Text Indexing").IsUnique(); 
    entity.Property(e => e.Active).HasDefaultValue(false); 
    entity.Property(e => e.EventCloseDate) 
     .HasColumnType("datetime") 
     .HasDefaultValueSql("'1/1/2038'"); 
    entity.Property(e => e.Name).HasMaxLength(1024); 
    entity.Property(e => e.PaxAllocationLimit).HasDefaultValue(10000); 
}); 

Lưu ý rằng nó có 2 các khóa - được tạo từ giàn giáo, bảng có khóa chính composite

Tuy nhiên với các yêu cầu của tôi với API, tôi chỉ cần một số nhận dạng chính - xóa khóa tổng hợp đã sửa lỗi tạo cột không hợp lệ

đang được cập nhật:

modelBuilder.Entity<Event>(entity=> { 
    entity.Property(e => e.EventId).HasColumnName("EventID"); 
    entity.HasKey(e => e.EventId); 
    entity.HasIndex(e => e.EventId).HasName("For Full Text Indexing").IsUnique(); 
    entity.Property(e => e.Active).HasDefaultValue(false); 
    entity.Property(e => e.EventCloseDate) 
     .HasColumnType("datetime") 
     .HasDefaultValueSql("'1/1/2038'"); 
    entity.Property(e => e.Name).HasMaxLength(1024); 
    entity.Property(e => e.PaxAllocationLimit).HasDefaultValue(10000); 
}); 
+0

Điều này cho đến khi không cố định, tôi đoán tôi vẫn nhận được lỗi tương tự. Rất buồn. –

+0

tại thời điểm tôi chỉ chạy vào quá nhiều vấn đề và tài liệu không đầy đủ (khoảng 3 tháng trước khi phát hành) - đoán tôi sẽ dính vào EF6 trong một thời gian – Danish

+0

Sau 3 tháng cũng có những thứ không thay đổi. EF 6. Buồn khi thấy họ đang nói RC 2 cuối cùng ngay cả khi những thứ cơ bản như 1 đến nhiều không hoạt động đúng. –

Các vấn đề liên quan