我有一个现有的数据库,我首先使用代码。我对我的 SQL 数据库中的表进行了一些清理,以确保在需要的地方有外键。我有一个名为 Inventory_Base 的表,它有一个名为 ClientID 的可空外键,它指向名为 Entity_Company 的表。Inventory_Base 映射到我的名为 ComputerEntity 的实体对象,Entity_Company 映射到我的名为 CompanyEntity 的实体对象。我相信我的导航道具设置正确,但如果我搞砸了,请告诉我。我遇到的问题是从未加载 CompanyEntity 导航属性。我尝试删除两者的导航属性,以便可以查看 ComputerEntity 对象中 ClientID 的值,但即使该列存在于数据库中,它也永远不会加载!我怀疑 EF 约定看到了“ID”这个词
我的 ComputerEntity 是这样定义的,我真的很想加载 CompanyEntity:
[Table("Inventory_Base")]
public class ComputerEntity
{
// primary key
[Key]
public int AssetID { get; set; }
// foreign keys
[ForeignKey("CompanyEntity")]
public int? ClientID { get; set; }
// navigation props
[ForeignKey("ClientID")]
public virtual CompanyEntity CompanyEntity { get; set; }
// these props are fine without custom mapping
public string Hostname { get; set; }
public string ServiceTag { get; set; }
}
这是我传说中的 CompanyEntity 永远不会加载:
[Table("Entity_Company")]
public class CompanyEntity
{
protected CompanyEntity() {}
// primary key
[Key]
public int ClientID { get; set; }
// foreign key
// nav props
public virtual ICollection<ComputerEntity> ComputerEntities { get; set; }
// regular props
// custom mappings
[Column("CompanyName", TypeName = "nvarchar(MAX)")]
public string Name { get; set; }
[Column("FQDN", TypeName = "nvarchar(MAX)")]
public string Domain { get; set; }
}
我正在尝试查找其主机名属性与输入匹配的计算机,并且该计算机属于特定公司。我有一个我正在查询的 DbSet,并假设由于存在导航属性,它可以访问关联的 CompanyEntity 对象的属性。到目前为止,我认为是错误的,并且我一生都看不到导致问题的原因。这是我尝试获取计算机的方式:
public ComputerEntity FindComputerByHostname(string hostname, string client)
{
var computer = DbSet.Where(x => x.Hostname == hostname && x.CompanyEntity.Name == client).FirstOrDefault(); // <-- always null!
var test = DbSet.Where(x.CompanyEntity.Name == client).ToList() // <-- never finds anything, which is why I suspect a non-working relationship
return computer ;
}
另一个奇怪的是,在我的 ComputerEntity 中,我必须使用 int 使 ClientID 为空?否则我会得到一个异常,即 ClientID 不能为空。当我查看数据库时,该列可以为空,但其中没有空值。诡异的。这是一个int的事实吗?以某种方式破坏关系?
更新
因此,我使用 EF 电动工具进行逆向工程,以尝试获取更多细节。它给了我所有丑陋的表名作为实体,这很好。CompanyEntity 现在是 Entity_Company,它拥有所有引用它的 ICollection。ComputerEntity 现在是 Inventory_Base,我遇到了同样的问题,它从未加载过。为了增加谜语,CompanyEntity(现在的 Entity_Company)的其他集合确实按预期导航!我检查了自动生成的映射文件,并且破坏的集合都有每个属性的 .IsRequired() 。正常工作的集合没有这个。此外,被破坏的集合都有它们的 ClientID 是 int 吗?而不是常规的不可为空的 int。虽然我不知道为什么,但我认为这是一个问题。ComputerEntity(现在的 Inventory_Base)专注于公司及其各自计算机之间手头的问题,具有可怕的 int? 在自动生成的映射文件中。我用 SELECT * FROM Inventory_Base WHERE ClientID IS NULL 检查了 SQL 数据库,但我什么也没得到。我尝试修改表以使 ClientID 列不可为空,并且 SQL 抱怨它不能这样做,因为无法重新创建表。通常我希望这是那里有一个空值......但没有。我可以修改与实体集合相对应的其他表,这些表已经很好地播放而没有问题。也许问题是损坏的 SQL 表?我不认为这是可能的,但如果有人知道一个 DBCC 命令来检查,那就太好了。为了使我的解决方案与这个问题保持一致,
在 ComputerEntity 内部我改变了:
[ForeignKey("CompanyEntity")]
public int? ClientID {get;set;}
至:
[ForeignKey("CompanyEntity")]
public int ClientID {get;set;}
现在,当我测试时,我得到了一个例外:
导航属性“ClientID”不是“ComputerEntity”类型的声明属性。验证它没有被明确地从模型中排除,并且它是一个有效的导航属性。
堆栈跟踪:在 System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureAssociations(EdmEntityType entityType, EdmModel model) 在 System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType, EdmModel model) 在System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel 模型) 在 System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(EdmModel 模型) 在 System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) 在 System.Data.Entity.Internal.RetryLazy 的 System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) 的 System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet
1.Initialize() 在 System.Data.Entity.Internal.Linq.InternalSet 1.get_InternalContext()
at System.Data.Entity.Infrastructure.DbQuery
1.System.Linq.IQueryable.get_Provider() 在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable 1 source, Expression
1 谓词) 在 Reporting.Data.InventoryRepository .FindComputerByHostname(String hostname, String client) in c:\Projects\Reporting\Data\Reporting.Data\InventoryRepository.cs:line 22 at Reporting.Services.InventoryService.GetComputerDetails(String hostname, String client) in c:\Projects\ Reporting\Business\Reporting.Services\InventoryService.cs:c:\Projects\Reporting\Tests\Reporting.Services.Tests\InventoryTests.cs 中 Reporting.Services.Tests.InventoryTests.GetComputerDetailsTest() 的第 29 行:第 39 行