Llo*_*oyd 8 sql-server entity-framework view .net-core
将 SQL Server 与 Entity Framework Core 3.1 结合使用。我有一个观点,我需要加入一个表。这显然在 SQL Server 中工作得很好。但我无法在 EF 中正确定义关系。从逻辑上来说,这应该是可能的。我发现没有在线文档表明这是不可能的。
我创建了一个小型 VisualStudio 项目来展示该问题。这些是项目中的所有文件。这是做作的,但非常简单。我使用“数据库优先”,因此这个示例符合我的实际应用程序。
映射到表的两个实体:
using System;
using System.Collections.Generic;
namespace ViewJoinIssue.Entities
{
public class ArticleEntity
{
public int ArticleId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public DateTime PublishDate { get; set; }
public ICollection<ArticleTagEntity> Tags { get; set; } = new List<ArticleTagEntity>();
}
}
Run Code Online (Sandbox Code Playgroud)
namespace ViewJoinIssue.Entities
{
public class ArticleTagEntity
{
public int ArticleTagId { get; set; }
public string Tag { get; set; }
public int ArticleId { get; set; }
public ArticleEntity Article { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
视图查询返回的项目的另一个类:
using System.Collections.Generic;
namespace ViewJoinIssue.Entities
{
public class ArticleViewItem
{
public int ArticleId { get; set; }
public string Title { get; set; }
public ICollection<ArticleTagEntity> Tags { get; set; } = new List<ArticleTagEntity>();
}
}
Run Code Online (Sandbox Code Playgroud)
每个的配置类:
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ViewJoinIssue.Entities;
namespace ViewJoinIssue.EntityConfiguration
{
public class ArticleConfiguration : IEntityTypeConfiguration<ArticleEntity>
{
public void Configure(EntityTypeBuilder<ArticleEntity> builder)
{
builder.HasKey(e => e.ArticleId);
builder.Property(e => e.ArticleId)
.HasColumnName("ArticleId")
.HasColumnType("int")
.ValueGeneratedOnAdd();
builder.Property(e => e.Title)
.HasColumnName("Title")
.HasColumnType("varchar(256)")
.HasMaxLength(256)
.IsRequired();
builder.Property(e => e.Author)
.HasColumnName("Author")
.HasColumnType("varchar(64)")
.HasMaxLength(64)
.IsRequired();
builder.Property(e => e.PublishDate)
.HasColumnName("PublishDate")
.HasColumnType("datetime")
.IsRequired();
builder.ToTable("Article");
builder.HasMany(e => e.Tags)
.WithOne(e => e.Article)
.HasForeignKey(e => e.ArticleId);
}
}
}
Run Code Online (Sandbox Code Playgroud)
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ViewJoinIssue.Entities;
namespace ViewJoinIssue.EntityConfiguration
{
public class ArticleTagConfiguration : IEntityTypeConfiguration<ArticleTagEntity>
{
public void Configure(EntityTypeBuilder<ArticleTagEntity> builder)
{
builder.HasKey(e => e.ArticleTagId);
builder.Property(e => e.ArticleTagId)
.HasColumnName("ArticleTagId")
.HasColumnType("int")
.ValueGeneratedOnAdd();
builder.Property(e => e.Tag)
.HasColumnName("Tag")
.HasColumnType("varchar(32)")
.HasMaxLength(32)
.IsRequired();
builder.ToTable("ArticleTag");
builder.HasOne(e => e.Article)
.WithMany(e => e.Tags)
.HasForeignKey(e => e.ArticleId);
}
}
}
Run Code Online (Sandbox Code Playgroud)
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ViewJoinIssue.Entities;
namespace ViewJoinIssue.EntityConfiguration
{
public class ArticleViewItemConfiguration : IEntityTypeConfiguration<ArticleViewItem>
{
public void Configure(EntityTypeBuilder<ArticleViewItem> builder)
{
builder.HasNoKey();
builder.Property(e => e.ArticleId)
.HasColumnName("ArticleId")
.HasColumnType("int")
.ValueGeneratedOnAdd();
builder.Property(e => e.Title)
.HasColumnName("Title")
.HasColumnType("varchar(256)")
.HasMaxLength(256)
.IsRequired();
builder.ToView("vwArticles");
builder.HasMany(e => e.Tags)
.WithOne()
.HasPrincipalKey(e => e.ArticleId);
}
}
}
Run Code Online (Sandbox Code Playgroud)
数据库上下文:
using Microsoft.EntityFrameworkCore;
using ViewJoinIssue.Entities;
using ViewJoinIssue.EntityConfiguration;
namespace ViewJoinIssue
{
public class DatabaseContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Data Source=(local)\\SQLSERVER2017;Initial Catalog=Articles;Trusted_Connection=true;MultipleActiveResultSets=true;Packet Size=4096");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new ArticleConfiguration());
modelBuilder.ApplyConfiguration(new ArticleTagConfiguration());
modelBuilder.ApplyConfiguration(new ArticleViewItemConfiguration());
base.OnModelCreating(modelBuilder);
}
public virtual DbSet<ArticleEntity> Articles { get; set; }
public virtual DbSet<ArticleTagEntity> ArticleTags { get; set; }
public virtual DbSet<ArticleViewItem> ArticleViewItems { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
以及简单的控制台程序:
using System;
using System.Linq;
namespace ViewJoinIssue
{
class Program
{
static void Main(string[] args)
{
var context = new DatabaseContext();
var viewItems = context.ArticleViewItems.ToList();
Console.WriteLine($"Found {viewItems.Count} items.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
您实际上可以编译并运行它来查看我收到的错误。不需要实际的数据库。
关于 ArticleViewItemConfiguration 中的这条语句...
builder.HasMany(e => e.Tags)
.WithOne()
.HasPrincipalKey(e => e.ArticleId);
Run Code Online (Sandbox Code Playgroud)
...它抛出这个异常:
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.SetOrAddForeignKey(ForeignKey foreignKey, InternalEntityTypeBuilder principalEntityTypeBuilder, IReadOnlyList`1 dependentProperties, Key principalKey, String navigationToPrincipalName, Nullable`1 isRequired, Nullable`1 configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.CreateForeignKey(InternalEntityTypeBuilder principalEntityTypeBuilder, IReadOnlyList`1 dependentProperties, Key principalKey, String navigationToPrincipalName, Nullable`1 isRequired, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasRelationshipInternal(EntityType targetEntityType, Key principalKey, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasRelationship(EntityType principalEntityType, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder`1.HasMany[TRelatedEntity](Expression`1 navigationExpression)
at ViewJoinIssue.EntityConfiguration.ArticleViewItemConfiguration.Configure(EntityTypeBuilder`1 builder) in C:\Work\PostBidShip\Code\ViewJoinIssue\EntityConfiguration\ArticleViewItemConfiguration.cs:line 26
at Microsoft.EntityFrameworkCore.ModelBuilder.ApplyConfiguration[TEntity](IEntityTypeConfiguration`1 configuration)
at ViewJoinIssue.DatabaseContext.OnModelCreating(ModelBuilder modelBuilder) in C:\Work\PostBidShip\Code\ViewJoinIssue\DatabaseContext.cs:line 20
at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_Model()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.CheckState()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at ViewJoinIssue.Program.Main(String[] args) in C:\Work\PostBidShip\Code\ViewJoinIssue\Program.cs:line 12
Run Code Online (Sandbox Code Playgroud)
它似乎正在尝试“设置或添加”外键。但这不适用于视图,因为它没有键。
我已经删除了“.HasPrincipleKey”方法调用,但我仍然遇到相同的异常。从逻辑上讲,我似乎需要告诉 EF 用于连接的属性,因为没有外键(它是一个视图)。
谁能指出我做错了什么?或者这可能是 EF 的错误。我在网上没有找到任何帮助;我已经搜索了所有我能想到的方法。大多数使用视图的示例都非常简单;大多数只是为了返回计数。
谢谢!!
| 归档时间: |
|
| 查看次数: |
3573 次 |
| 最近记录: |