[英]Entity Framework Core 2.1 trouble with relationships
我正在嘗試將以下 sql 查詢轉換為實體框架,但遇到列未加入表的問題。
SELECT
a.TABLE_NAME AS tableName,
b.COLUMN_NAME AS columnName,
b.DATA_TYPE AS dataType,
CASE WHEN b.IS_NULLABLE = 'NO' THEN 'FALSE' ELSE 'TRUE' END AS allowNull
FROM INFORMATION_SCHEMA.TABLES a
INNER JOIN INFORMATION_SCHEMA.COLUMNS b ON a.TABLE_NAME = b.TABLE_NAME
這是我到目前為止
數據庫上下文:
using Microsoft.EntityFrameworkCore;
namespace EFCoreTest.Models
{
public class InformationContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=localhost;Database=master;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Table>()
.HasKey(t => new {t.tableName, t.catalogName, t.schemaName});
modelBuilder.Entity<Column>()
.HasOne(c => c.table)
.WithMany(c => c.columns)
.HasForeignKey(c => new {c.tableName, c.catalogName, c.schemaName});
}
public DbSet<Table> Tables {get; set;}
public DbSet<Column> Columns {get; set;}
}
}
列類:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreTest.Models
{
[Table("COLUMNS", Schema = "INFORMATION_SCHEMA")]
public class Column
{
[Key]
[Column("COLUMN_NAME")]
public String columnName {get; set;}
[Column("DATA_TYPE")]
public String dataType {get; set;}
[Column("IS_NULLABLE")]
public String allowNUlls {get; set;}
[ForeignKey("Table")]
[Column("TABLE_NAME")]
public String tableName {get; set;}
[ForeignKey("Table")]
[Column("TABLE_CATALOG")]
public String catalogName {get; set;}
[ForeignKey("Table")]
[Column("TABLE_SCHEMA")]
public String schemaName {get; set;}
public Table table {get; set;}
}
}
表類:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCoreTest.Models
{
[Table("TABLES" , Schema = "INFORMATION_SCHEMA")]
public class Table
{
[Key]
[Column("TABLE_NAME")]
public String tableName {get; set;}
[Key]
[Column("TABLE_CATALOG")]
public String catalogName {get; set;}
[Key]
[Column("TABLE_SCHEMA")]
public String schemaName {get; set;}
public ICollection<Column> columns {get; set;}
protected Table() {columns = new List<Column>();}
}
}
主要的:
using System;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using EFCoreTest.Models;
namespace EFCoreTest
{
class Program
{
static void Main(string[] args)
{
using(InformationContext context = new InformationContext())
{
var results = context.Tables.Include(t => t.columns).ToList();
foreach(var t in results)
{
Console.WriteLine(t.tableName);
Console.WriteLine("-----------------------------");
var columns = t.columns.ToList();
foreach(var c in columns)
{
Console.WriteLine(c.columnName);
}
Console.WriteLine("");
}
}
}
}
}
代碼運行良好,但在檢查表實例時,所有列實例都為空。 我有一種感覺,它與表和列之間的關系有關,但在查看了 efcore2.1 關系的文檔后,我無法弄清楚我做錯了什么。
任何幫助,將不勝感激。
更新:使用附加鍵和相關數據加載更新代碼。
嘗試這個:
context.Tables.Include(t => t.columns).ToList();
首先,歡迎堆棧溢出。
根據 Gonzalo 的回答,Include 語句將讓您包含一個集合:
context.Tables.Include(t => t.columns).ToList();
然而,我想強調一些其他小的改進,您可以做一些其他的小改進,使您的代碼隨着時間的推移變得更加健壯和可維護。
請記住使用受保護的構造函數初始化您的實體以避免空指針異常,因為在大多數情況下,返回帶有實體的空集合應該是業務應用程序的有效場景:
受保護的表(){列=新列表(); }
使用 ICollection 而不是 List 來定義集合。
C# 中的通用命名標准是在聲明公共屬性和集合時使用 Pascal 大小寫。
您正在混合兩種定義關系的不同方式。
這個:
modelBuilder.Entity<Column>()
.HasOne(c => c.table)
.WithMany(c => c.columns)
.HasForeignKey(c => c.tableForeignKey);
而你在實體的相關屬性上使用的注解,比如 [Key] 實際上是兩種不同的方式來做同樣的事情。 首先使用一個,最好是代碼,即通過配置。
5、我建議使用單獨的實體類型配置文件,否則你的架構最終將很難維護,例如基本配置:
public class BaseEntityConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
where TEntity : BaseEntity
{
public virtual void Configure(EntityTypeBuilder<TEntity> builder)
{
builder.HasKey(be => be.Guid);
builder.Property(be => be.CreatedBy).IsRequired();
builder.Property(be => be.CreatedDate).IsRequired();
}
}
public class AddressConfiguration : BaseEntityConfiguration<Address>
{
public override void Configure(EntityTypeBuilder<Address> builder)
{
builder.HasOne(a => a.Contact)
.WithMany(c => c.Addresses)
.HasForeignKey(a => a.ContactGuid);
builder.HasOne(a => a.Partner)
.WithMany(a => a.Addresses)
.HasForeignKey(a => a.PartnerGuid);
base.Configure(builder);
}
}
並在上下文中:
modelBuilder.ApplyConfiguration(new AddressConfiguration());
正如您可能注意到的那樣,我還使用 BaseEntity 來保存所有重復屬性,例如 Id,並從中派生出我的所有實體。 我建議你也這樣做。
希望有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.