C# 如何在代码隐藏中设置导航属性的值?
我有一个名为C# 如何在代码隐藏中设置导航属性的值?,c#,entity-framework,navigation-properties,C#,Entity Framework,Navigation Properties,我有一个名为Cost的实体,它的必需属性为CostType Cost类有一个GetNew()方法,用于设置所有成本的默认值: public static GetNew() { Cost cost = new Cost (); foo.CostType = Lists.CostTypes.FirstOrDefault(); // Other Default Values return foo; } 列表.CostTypes是一个静态列表,在启动时从EF中提取并在
Cost
的实体,它的必需属性为CostType
Cost
类有一个GetNew()
方法,用于设置所有成本的默认值:
public static GetNew()
{
Cost cost = new Cost ();
foo.CostType = Lists.CostTypes.FirstOrDefault();
// Other Default Values
return foo;
}
列表.CostTypes
是一个静态列表,在启动时从EF中提取并在组合框中使用
首先在GetNew()
方法中设置CostType之后,我在代码中设置CostType时遇到问题
例如,以下代码读取excel文件,并根据excel文件中的列设置默认类型,如果找不到匹配项,则设置为null
Cost cost = Cost.GetNew();
cost.CostType = Lists.CostTypes.FirstOrDefault(t => t.Name == row[0].ToString());
我的问题是,在保存操作期间,我遇到以下错误:
操作失败:无法更改关系,因为
一个或多个外键属性不可为空。当
对关系进行更改时,相关的外键属性为
设置为空值。如果外键不支持空值,
必须定义新关系,外键属性必须为
指定了另一个非空值,或者必须为不相关的对象
删除
我的添加操作如下所示:
public static void AddObject(EntityObject obj, string entitySetName)
{
context.AddObject(entitySetName, obj);
context.SaveChanges();
}
- 如果在读取excel文件时删除手动设置成本的代码行,则保存工作正常李>
- 如果我将代码行更改为读取Lists.Costs[2],则可以节省罚款李>
- 如果我删除
中设置默认值的代码行,我会收到一个错误,告诉我我违反了CostTypes的PK规则,这意味着它试图插入成本类型GetNew()
- 将显示类型的组合框更改为其他类型仍然会产生相同的错误
- 从excel文件加载成本后,我的常规添加/编辑表单在更改类型并尝试保存时会抛出相同的错误。如果我不加载excel文件,它们工作正常
在一个表中,成本
在另一个表中。在数据库中,成本类型
列不允许为空,并且是Costs.TypeId
的外键。两个表的CostTypes
字段都是自动生成的Id
- 我的EF模型只是添加了两个数据库表的通用模型。我对它所做的唯一更改是重命名一些字段并删除
Navigation属性CostTypes.Costs
- 导入的Excel文件将大多数成本映射到匹配的
,但是Excel文件中的字符串可能与CostType.Name
不匹配,因此CostType
列出.CostTypes.FirstOrDefault(t=>t.Name==行[0].ToString()可以为
Cost.Type
属性指定一个
NULL
NULL值。但这似乎不是问题,因为表单仍然会显示成本列表及其默认选定项目。成本类型为
ComboBox`中选择项目,并触发必须在保存前更正的验证错误CostType的项目没有在成本类型
CostType
列表的代码为
public static List<T> GetList<T>(string sortProperty)
where T : EntityObject
{
using (var context = new TContext())
{
return ApplyOrder<T>(context.CreateObjectSet<T>(), sortProperty, "OrderBy").ToList();
}
}
这并不是一个令人满意的答案,而是根据问题中的信息和对问题的评论,猜测和开放性问题的混合:
- 首先:您的列表
列表。成本类型
显然包含从您稍后添加和保存新对象的上下文中分离出来的实体。因为您有一个
块:using
您正在另一个上下文中检索using(var context=new TContext())
实体CostType
- 要告诉EF这些
实体已经存在于数据库中,您必须将这些实体附加到您保存更改的第二个上下文(CostType
)中(或在您检索列表的方法中使用相同的上下文)。我在你的代码中没有看到你这样做。(context.CostTypes.attach(CostType)
是导航引用属性,不是外键属性,对吗?)CostType
另一方面,当<代码> CasyType 实体没有被附加时,你应该在你的数据库中得到重复的成本类型,因为EF会把它们看作新的对象(插入到数据库中)。当您为您的
成本实体调用AddObject
时,因为EF将始终将分离实体的整个对象图置于Added
状态。在工作示例中,数据库中是否有重复的成本类型?如果没有,那么代码片段中缺少一些重要的内容
最后一段假设CostType
的键是在数据库中自动生成的,如您所说。否则,您将得到PK约束冲突,而不是重复的实体
如果CostType
和Cost
的键真的是自动生成的身份,我想知道你提到的PK违规是从哪里来的。每次插入都会创建一个新的唯一主键。永远不会发生PK违例事件。您能详细显示异常消息吗
您是否检查了所有要保存的成本
实体是否确实具有非空的成本类型
属性(在用户修复了所有验证错误之后)?我在您的代码中找不到任何其他可能的原因来解释为什么您会得到“关系无法更改异常”,除了至少有一个成本
对象成本类型
为空
我想出来了。。。。这是一些不同事物的混合
创建新的
成本和sett
public static class Lists
{
public static List<CostType> CostTypes { get; private set; }
static Lists()
{
CostTypes = DAL<CostEntities>.GetList<CostType>("Name");
}
}