我有一个现有的数据库,我首先使用代码。我对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不能为null的异常。当我查看数据库时,该列可以为空,但其中没有空值。奇怪的。这是一个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和CompanyEntity。
在ComputerEntity内部我改变了:
[ForeignKey("CompanyEntity")]
public int? ClientID {get;set;}
为:
[ForeignKey("CompanyEntity")]
public int ClientID {get;set;}
现在,当我测试时,我得到一个例外:
导航属性&#39; ClientID&#39;不是类型&#39; ComputerEntity&#39;的声明属性。验证它是否未从模型中明确排除,并且它是有效的导航属性。
堆栈跟踪:
在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.DbModelBuilder.Build(DbConnection providerConnection)
在System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
在System.Data.Entity.Internal.RetryLazy 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谓词)
在C:\ Projects \ Reporting \ Data \ Reporting.Data \ InventoryRepository.cs中的Reporting.Data.InventoryRepository.FindComputerByHostname(String hostname,String client):第22行
在C:\ Projects \ Reporting \ Business \ Reporting.Services \ InventoryService.cs中的Reporting.Services.InventoryService.GetComputerDetails(String hostname,String client):第29行
在C:\ Projects \ Reporting \ Tests \ Reporting.Services.Tests \ InventoryTests.cs中的Reporting.Services.Tests.InventoryTests.GetComputerDetailsTest()中:第39行
答案 0 :(得分:0)
如果我将外键ClientID设置为int?它现在也神奇地起作用了。我怀疑这是因为没有更多的空键,即使我说它可以为空。我不打算将空值重新引入到ComputerEntity所在的表中,但是当我完成这个项目时,我很确定我会找到更多情况。如果有人可以给我一个关于可以为空的外键如何使用自动EF映射的可靠答案,我很乐意接受这个答案。我试图远离FluentAPI并直接进行数据注释。也许答案是删除任何导致我胃灼热的惯例。