实体框架:它到底从哪里获取这些列?

发布于 2024-12-17 14:41:40 字数 2074 浏览 0 评论 0原文

我们正在尝试让实体框架在我们的商店中使用现有的数据库(因此,更改数据库模式不是一个选项),并且我们创建的用于测试事物的单元测试显示了一些非常奇怪的行为。

这是它为我们拥有的特定对象吐出的 SQL:

SELECT 
[Extent1].[CommentTypeId] AS [CommentTypeId], 
[Extent1].[DataPartId] AS [DataPartId], 
[Extent1].[CommentId] AS [CommentId], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Message] AS [Message], 
[Extent1].[From] AS [From], 
[Extent1].[Likes] AS [Likes], 
[Extent1].[SourceTypeId] AS [SourceTypeId], 
[Extent1].[StatusMessage_DataPartId] AS [StatusMessage_DataPartId], 
[Extent1].[Album_DataPartId] AS [Album_DataPartId]
FROM [dbo].[Comments] AS [Extent1]

正如您可能注意到的,请求的最后两列与其他列不同。那是因为它们实际上并不存在,而且我们不知道实体为什么要求它们!我们的配置文件和 POCO 都没有提及它们。事实上,就我们的数据库而言,它们是完全独立的概念,根本没有直接关系。

它从哪里获取这些列,我如何告诉它将其删除?

编辑:为了回答下面的一些问题, 1)我们使用实体框架4.2。我们正在使用流畅的映射。

2) POCO 本身看起来像这样,为了简洁起见,去掉了等式混乱:

public long DataPartId { get; set; }
public string CommentId { get; set; }
public DateTime? CreatedTime { get; set; }
public string Message { get; set; }
public string From { get; set; }
public int? Likes { get; set; }
public string SourceTypeId { get; set; }
public int CommentTypeId { get; set; }

public virtual DataPart DataPart { get; set; }
public virtual CommentType CommentType { get; set; }

3) 我们没有使用 edmx。我们有一个自定义的 DbContext。没有太多非常有趣的台词。这两个可能很有趣:

    Configuration.LazyLoadingEnabled = true;
    Configuration.ProxyCreationEnabled = true;

除此之外,上下文文件很多

modelBuilder.Configurations.Add(new WhateverConfiguration()) 

,并且

public IDbSet<WhateverPoco> PocoDatabaseTableAccessor { get; set; }

4)我们从数据库优先开始,但这不起作用,所以我们目前正在进行代码优先。

5) 这是特定 POCO 的配置的核心:

    HasRequired (x => x.DataPart)
        .WithRequiredDependent (x => x.Comment);

    HasRequired (x => x.CommentType)
        .WithMany (x => x.Comments)
        .HasForeignKey (x => x.CommentTypeId);

    HasKey (x => x.DataPartId);
    ToTable ("Comments", "dbo");

We are trying to get Entity framework working at our shop with an existing database (and therefore, changing the database schema is NOT an option), and the unit tests we created to test things are showing some really strange behavior.

This is the SQL it spits out for a specific object we have:

SELECT 
[Extent1].[CommentTypeId] AS [CommentTypeId], 
[Extent1].[DataPartId] AS [DataPartId], 
[Extent1].[CommentId] AS [CommentId], 
[Extent1].[CreatedTime] AS [CreatedTime], 
[Extent1].[Message] AS [Message], 
[Extent1].[From] AS [From], 
[Extent1].[Likes] AS [Likes], 
[Extent1].[SourceTypeId] AS [SourceTypeId], 
[Extent1].[StatusMessage_DataPartId] AS [StatusMessage_DataPartId], 
[Extent1].[Album_DataPartId] AS [Album_DataPartId]
FROM [dbo].[Comments] AS [Extent1]

The last two columns requested, as you might notice, are not like the others. That's because they don't actually exist, and we have no idea why Entity is requesting them! Neither our configuration files nor our POCOs make any mention of them at all. In fact, as far as our database goes, they're completely separate concepts and aren't directly related at all.

Where is it getting these columns from, and how do I tell it to cut it out?

EDIT: To respond to some of the questions below,
1) We are using Entity Framework 4.2. We are using fluent mapping.

2) The POCO itself looks like this, with the equality mess cut out for the sake of brevity:

public long DataPartId { get; set; }
public string CommentId { get; set; }
public DateTime? CreatedTime { get; set; }
public string Message { get; set; }
public string From { get; set; }
public int? Likes { get; set; }
public string SourceTypeId { get; set; }
public int CommentTypeId { get; set; }

public virtual DataPart DataPart { get; set; }
public virtual CommentType CommentType { get; set; }

3) We are not using edmx. We have a custom DbContext. There are not too many lines that are terribly interesting. These two are probably of interest:

    Configuration.LazyLoadingEnabled = true;
    Configuration.ProxyCreationEnabled = true;

Beyond that, the Context file is a lot of

modelBuilder.Configurations.Add(new WhateverConfiguration()) 

and

public IDbSet<WhateverPoco> PocoDatabaseTableAccessor { get; set; }

4) We started with db-first, but that didn't work, so we're currently doing code-first.

5) This is the guts of the config for that specific POCO:

    HasRequired (x => x.DataPart)
        .WithRequiredDependent (x => x.Comment);

    HasRequired (x => x.CommentType)
        .WithMany (x => x.Comments)
        .HasForeignKey (x => x.CommentTypeId);

    HasKey (x => x.DataPartId);
    ToTable ("Comments", "dbo");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

神妖 2024-12-24 14:41:40

问题不在于您显示的映射或类。检查您的 AlbumStatusMessage 类。它们是实体吗?它们被映射了吗?他们有评论的集合导航属性吗?如果是,EF 预计 Comment 必须对这些表具有 FK。如果表没有此类列,则无法将这些导航属性映射到这些实体中。

顺便提一句。 Comments 表中的 id 不应该是 CommentId 而不是 DataPartId 吗?

The problem is not in the mapping or class you showed. Check your Album and StatusMessage classes. Are they entities? Are they mapped? Do they have collection navigation properties to comments? If yes EF expects that Comment must have FK to these tables. If the table doesn't have such column you cannot have these navigation properties mapped in those entities.

Btw. Shouldn't the id in Comments table be CommentId instead of DataPartId?

晨光如昨 2024-12-24 14:41:40

实体框架与 MVC 一样,使用了大量约定优于配置。这意味着它会假设某些事情,除非你告诉它不要这样做。

然而,根据您提供的信息,这里确实有些奇怪。根据 SQL 查询,这来自 Comments 表,但是您的流畅映射表明 DataPartId 是主键。您是否有其他主键流畅映射?如果没有,您的映射可能是错误的。您是否检查过生成的实际数据库以查看数据模型是否与您想要执行的操作相匹配?

我的猜测是,您的 StatusMessage 和 Album 类具有 Comment 的导航属性,但由于您仅将 DataPartId 定义为主键,因此这是它用于查找评论的值,而不是 CommentId。

Entity Framework, like MVC, uses a lot of convention over configuration. That means it assumes certain things unless you tell it not to.

However, something is really strange here based on the information you supplied. According to the SQL query, this is coming from the Comments table, however your fluent mapping says that DataPartId is the primary key. Do you have additional primary key fluent mappings? If not, your mappings may be wrong. Have you checked the actual database generated to see if the data model matches what you are trying to do?

My guess is that your StatusMessage and Album classes have navigational properties to Comment, but since you have only defined DataPartId as your primary key, that is the value it is using to look up the comments, not CommentId.

耳根太软 2024-12-24 14:41:40

在 XML 编辑器中打开 .edmx 并搜索这些列。它们一定在你的模型中的某个地方。

编辑:您原来的问题没有提到您首先使用代码。我想知道您首先遇到的数据库问题是什么,通常工作得很好。对于代码优先或模型优先,您通常在创建模型后创建数据库(使用生成的 SQL 脚本)。

您将最后两个属性声明为虚拟属性,这就是生成的 SQL 看起来不同的原因。从您向我们展示的代码中,我们无法看出对相册的引用来自何处。

因为您拥有数据库,所以我会在一个项目中从模型生成 .edmx。然后,您可以使用 POCO 代码生成器或自跟踪实体生成器来生成实体并将它们存储在不同的项目中。或者您可以像已有的那样手动编写它们。属性名称必须与数据库中的列相对应。

Open the .edmx in a XML-Editor and search for these columns. They must be somewhere in your model.

EDIT: your original question didn't mention that you are using code first. I wonder what your trouble was with Database first, that usually works fine well. With code first or model first, you normally create the database after creating the model (using generated SQL scripts).

You declared the last two properties as virtual, that's why the generated SQL looks different. From the code you are showing us we cannot see where the reference to Album comes from.

Because you have the database, I would generate the .edmx from the model in one project. Then you can use a POCO code generator or a Self-tracking entity generator to generate the entities and store them in a different project. Or you can write them manually as you already have. The property names must correspond with the columns in the database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文