如何根据元数据 类 正确确定 Entity Framework 中的关系?
How do I properly determine the relationships in Entity Framework from metadata classes?
我目前正在使用一个收集 API 数据的包 (Crayon API NuGet Package),但是,我正在努力通过 Entity Framework 来实现它。我正在从 Crayon 中提取数据,我想将其存储到数据库中,代码很好,只是 entity framework 部分没有按我希望的那样工作。当我 运行 迁移时,我收到此错误:
“无法确定类型 'Price' 的导航 'BillingStatement.TotalSalesPrice' 表示的关系。要么手动配置关系,要么使用 '[ 忽略此 属性 NotMapped]' 属性或在 'OnModelCreating' 中使用 'EntityTypeBuilder.Ignore'。"
所以从这个错误的外观来看,我需要配置关系,但我不确定如何通过元数据来做到这一点,因为 API 数据和 classes 设置在包(元数据)。但这是我使用的 Entity Framework 模型。
public class CrayonDbContext : DbContext
{
private const string connectionString = @"myserver";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<BillingStatement> BillingStatements { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AddressData>().HasNoKey();
modelBuilder.Entity<Price>().HasNoKey();
}
}
这是它正在使用的元数据中的 BillingStatement class。
namespace Crayon.Api.Sdk.Domain.Csp
{
public class BillingStatement
{
public BillingStatement();
public int Id { get; set; }
public Price TotalSalesPrice { get; set; }
public ObjectReference InvoiceProfile { get; set; }
public ObjectReference Organization { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public ProvisionType ProvisionType { get; set; }
}
}
现在这里是先前显示的帐单 class 中引用的 classes。
public class Price
{
public Price();
public decimal Value { get; set; }
public string CurrencyCode { get; set; }
}
public class ObjectReference
{
public ObjectReference();
public int Id { get; set; }
public string Name { get; set; }
}
public enum ProvisionType
{
None = 0,
Seat = 1,
Usage = 2,
OneTime = 3,
Crayon = 4,
AzureMarketplace = 5
}
我知道当涉及规范化时,它开始变得更加复杂。我会用这个做什么?我将如何配置关系?是否有任何好的来源 material 可以帮助处理元数据 classes,我可以在其中搭建表格并按预期存储数据?
如有任何帮助,我们将不胜感激。
您需要做出一些数据库设计决策才能使其正常工作。对于那个特定的价格,应该像这样配置为 Owned Entity Type:
public class BillingStatement
{
public int Id { get; set; }
public Price TotalSalesPrice { get; set; }
public ObjectReference InvoiceProfile { get; set; }
public ObjectReference Organization { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public ProvisionType ProvisionType { get; set; }
}
public class ObjectReference
{
public int Id { get; set; }
public string Name { get; set; }
}
public enum ProvisionType
{
None = 0,
Seat = 1,
Usage = 2,
OneTime = 3,
Crayon = 4,
AzureMarketplace = 5
}
public class Price
{
public decimal Value { get; set; }
public string CurrencyCode { get; set; }
}
public class Db : DbContext
{
public Db() : base()
{
}
private static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddFilter((category, level) =>
category == DbLoggerCategory.Database.Command.Name
&& level == LogLevel.Debug).AddConsole();
});
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var constr = "Server=localhost; database=efcore5test; integrated security = true; TrustServerCertificate=true";
optionsBuilder.UseLoggerFactory(loggerFactory)
.UseSqlServer(constr, o => o.UseRelationalNulls());
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BillingStatement>().OwnsOne<Price>( s => s.TotalSalesPrice);
modelBuilder.Entity<BillingStatement>().OwnsOne<ObjectReference>(s => s.InvoiceProfile);
modelBuilder.Entity<BillingStatement>().OwnsOne<ObjectReference>(s => s.Organization);
base.OnModelCreating(modelBuilder);
}
}
这将创建一个像这样的 table:
CREATE TABLE [BillingStatement] (
[Id] int NOT NULL IDENTITY,
[TotalSalesPrice_Value] decimal(18,2) NULL,
[TotalSalesPrice_CurrencyCode] nvarchar(max) NULL,
[InvoiceProfile_Id] int NULL,
[InvoiceProfile_Name] nvarchar(max) NULL,
[Organization_Id] int NULL,
[Organization_Name] nvarchar(max) NULL,
[StartDate] datetimeoffset NOT NULL,
[EndDate] datetimeoffset NOT NULL,
[ProvisionType] int NOT NULL,
CONSTRAINT [PK_BillingStatement] PRIMARY KEY ([Id])
);
您可能还想用目标对象的适当导航属性替换 ObjectReference
对象,因为这似乎是您可能不想要的 API 实现的产物你的数据库。
我目前正在使用一个收集 API 数据的包 (Crayon API NuGet Package),但是,我正在努力通过 Entity Framework 来实现它。我正在从 Crayon 中提取数据,我想将其存储到数据库中,代码很好,只是 entity framework 部分没有按我希望的那样工作。当我 运行 迁移时,我收到此错误:
“无法确定类型 'Price' 的导航 'BillingStatement.TotalSalesPrice' 表示的关系。要么手动配置关系,要么使用 '[ 忽略此 属性 NotMapped]' 属性或在 'OnModelCreating' 中使用 'EntityTypeBuilder.Ignore'。"
所以从这个错误的外观来看,我需要配置关系,但我不确定如何通过元数据来做到这一点,因为 API 数据和 classes 设置在包(元数据)。但这是我使用的 Entity Framework 模型。
public class CrayonDbContext : DbContext
{
private const string connectionString = @"myserver";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<BillingStatement> BillingStatements { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AddressData>().HasNoKey();
modelBuilder.Entity<Price>().HasNoKey();
}
}
这是它正在使用的元数据中的 BillingStatement class。
namespace Crayon.Api.Sdk.Domain.Csp
{
public class BillingStatement
{
public BillingStatement();
public int Id { get; set; }
public Price TotalSalesPrice { get; set; }
public ObjectReference InvoiceProfile { get; set; }
public ObjectReference Organization { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public ProvisionType ProvisionType { get; set; }
}
}
现在这里是先前显示的帐单 class 中引用的 classes。
public class Price
{
public Price();
public decimal Value { get; set; }
public string CurrencyCode { get; set; }
}
public class ObjectReference
{
public ObjectReference();
public int Id { get; set; }
public string Name { get; set; }
}
public enum ProvisionType
{
None = 0,
Seat = 1,
Usage = 2,
OneTime = 3,
Crayon = 4,
AzureMarketplace = 5
}
我知道当涉及规范化时,它开始变得更加复杂。我会用这个做什么?我将如何配置关系?是否有任何好的来源 material 可以帮助处理元数据 classes,我可以在其中搭建表格并按预期存储数据?
如有任何帮助,我们将不胜感激。
您需要做出一些数据库设计决策才能使其正常工作。对于那个特定的价格,应该像这样配置为 Owned Entity Type:
public class BillingStatement
{
public int Id { get; set; }
public Price TotalSalesPrice { get; set; }
public ObjectReference InvoiceProfile { get; set; }
public ObjectReference Organization { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
public ProvisionType ProvisionType { get; set; }
}
public class ObjectReference
{
public int Id { get; set; }
public string Name { get; set; }
}
public enum ProvisionType
{
None = 0,
Seat = 1,
Usage = 2,
OneTime = 3,
Crayon = 4,
AzureMarketplace = 5
}
public class Price
{
public decimal Value { get; set; }
public string CurrencyCode { get; set; }
}
public class Db : DbContext
{
public Db() : base()
{
}
private static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddFilter((category, level) =>
category == DbLoggerCategory.Database.Command.Name
&& level == LogLevel.Debug).AddConsole();
});
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var constr = "Server=localhost; database=efcore5test; integrated security = true; TrustServerCertificate=true";
optionsBuilder.UseLoggerFactory(loggerFactory)
.UseSqlServer(constr, o => o.UseRelationalNulls());
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BillingStatement>().OwnsOne<Price>( s => s.TotalSalesPrice);
modelBuilder.Entity<BillingStatement>().OwnsOne<ObjectReference>(s => s.InvoiceProfile);
modelBuilder.Entity<BillingStatement>().OwnsOne<ObjectReference>(s => s.Organization);
base.OnModelCreating(modelBuilder);
}
}
这将创建一个像这样的 table:
CREATE TABLE [BillingStatement] (
[Id] int NOT NULL IDENTITY,
[TotalSalesPrice_Value] decimal(18,2) NULL,
[TotalSalesPrice_CurrencyCode] nvarchar(max) NULL,
[InvoiceProfile_Id] int NULL,
[InvoiceProfile_Name] nvarchar(max) NULL,
[Organization_Id] int NULL,
[Organization_Name] nvarchar(max) NULL,
[StartDate] datetimeoffset NOT NULL,
[EndDate] datetimeoffset NOT NULL,
[ProvisionType] int NOT NULL,
CONSTRAINT [PK_BillingStatement] PRIMARY KEY ([Id])
);
您可能还想用目标对象的适当导航属性替换 ObjectReference
对象,因为这似乎是您可能不想要的 API 实现的产物你的数据库。