当行具有空值时,实体框架返回空对象

3

我有一个现有的数据库(我不能以任何方式修改),我想使用EF进行编码。这个数据库没有主键、外键或实际关系,所有的表之间似乎都是由应用程序处理的。对于大多数表/实体,这是很简单的。然而,我有一个类如下(简化)的,我正在努力解决它。

[Table("tableName")]
public class MyClass
{
    [Key]
    [Column("id")]
    public int? Id { get; set; }

    [Column("name")]
    public string CompanyName { get; set; }

    [Column("address")]
    public string Address { get; set; }
}

_context.MyClasses.Where(x => x.Address == "something") 这样的语句是可以正常工作的。然而,当数据库中的 id 列为 NULL 时,我会得到一个空对象 - 即使 CompanyName 和 Address 有值。而我需要这些值,无论 id(或其他任何东西)是否为空。是否有一种方法可以强制 EF 生成对象并忽略空列?

移除或移动 [Key] 属性会导致异常,例如 "必须有一个键列"(如果有任何匹配的其他类,则 Id 列也用于将其映射到此类的集合中)。

更新 不要将 Id 列视为实际标识符。它基本上只是一个带有愚蠢名称的整数。


2
一个PK怎么可能是null呢?这不是技术选项的问题,而是使用方式的问题。 - user57508
它在数据库中并不是真正的主键,只是似乎必须在实体中标记为关键字,才能将一些其他实体收集到其中... - Arve Systad
1
顺便提一下,“必须有关键列”存在一个解决方法:只需将所有列标记为关键列(就像EF在模糊视图中所做的那样),或添加一个新列(自动增量)。 - user57508
1
如果“id”可以为空,则你就没那么幸运了。你需要一个非空键来使用EF。如果名称和地址是唯一且非空的,你可以将其作为EF的主键... - Denis Troller
1
这样的数据库并不适合作为EF和NH的OR/M,但也许您可以使用Dapper Dot Net来获得一些满意度。 - Felice Pollano
4个回答

3

如果您的数据库中的属性是可空的,则无法在Id属性上方放置KeyAttribute。这就是导致您出现问题的原因...

主键不能为null,但我猜您已经知道了...


这似乎是合理的,但是如果我把它删除,为什么EF会抛出异常呢?如上所述,数据库中没有实际的PK。 - Arve Systad
@ArveSystad,不,这是不合理的。考虑一个没有任何唯一键的日志表(你可能有它,但通常不需要)。这是否意味着您不能使用EF查询此类表? - UserControl

2
您必须拥有一个包含值的Key列才能使此功能正常工作。将列标记为Key表示该列是该表的主键列。
如果Key列包含空值,则该行不会返回给客户端。如果Id列不是主键(因为它可能包含空值),则需要添加一个新列来充当主键。

但是,为什么我不能删除Key属性而不返回异常呢?我有其他类似的表格,它们没有键(在数据库或模型中都没有)。 - Arve Systad
@ArveSystad - 因为你需要一个“Key”列。 - ChrisF
我有另一个类/表,它可以完美地工作而不需要这个,所以我真的看不出为什么... - Arve Systad
不用在意我说的话。另一个实体当然使用EntityNameId约定来获取它的键。 - Arve Systad
似乎解决方案要么是让负责人更改数据库,要么手动编写SQL。 :-( - Arve Systad

1

你需要有一个键列。EF 要求你必须有一个。但是,对于你的目的,你可以使用另一种替代方式:

将你的 Id 的 StoreGeneratedPattern 属性设置为 Identity,并将其生成和管理交给 EF。不要将 Id 用于可空的目的;创建另一个列,如 MyId,它是可空的而且不是 EntityKey,然后按照你想要的任何方式使用它。


我该在哪里设置StoreGeneratedPattern属性?它似乎是一个模型设计师的东西,而我没有edmx文件。 - Arve Systad
我相信你可以在模型定义的顶部放置StoreGeneratedPattern="Identity"属性,尽管我不确定。 - Halo

1

解决方案

就像Andreas Niedermair在我的问题上评论的那样,我现在已经在数据库中的多个列中添加了[Key]。我发现,在这种情况下,四个列作为组合键总是唯一的。

由于我从未向数据库插入新内容,所以在这种边缘情况下,这似乎是一个不错的解决方案,我想。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接