简体   繁体   English

如何在后面的代码中设置导航属性的值?

[英]How can I set the value of a Navigation Property in the code behind?

I have an Entity called Cost , which has a required property of CostType 我有一个称为Cost的实体,该实体具有CostType的必需属性

The Cost class has a GetNew() method which sets all the Cost's defaults: Cost类具有一个GetNew()方法,该方法设置所有Cost的默认值:

public static GetNew()
{
    Cost cost = new Cost ();
    foo.CostType = Lists.CostTypes.FirstOrDefault();
    // Other Default Values

    return foo;
}

The Lists.CostTypes is a static list which is pulled from EF at startup and used in ComboBoxes Lists.CostTypes是一个静态列表,该列表在启动时从EF提取并在ComboBoxes中使用

I am having problems setting the CostType within my code, after first setting it in the GetNew() method. 在首先在GetNew()方法中设置CostType后,在设置代码中遇到问题。

For example, the following code reads an excel file, and sets the default type based on a column in the Excel file, or null if it can't find a match 例如,以下代码读取一个excel文件,并根据Excel文件中的列设置默认类型;如果找不到匹配项,则为null

Cost cost = Cost.GetNew();
cost.CostType = Lists.CostTypes.FirstOrDefault(t => t.Name == row[0].ToString());

My problem is, during the Save operation I get the following error: 我的问题是,在“保存”操作期间,出现以下错误:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. 操作失败:无法更改关系,因为一个或多个外键属性不可为空。 When a change is made to a relationship, the related foreign-key property is set to a null value. 当对关系进行更改时,相关的外键属性将设置为空值。 If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted. 如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

My Add Operation looks like this: 我的添加操作如下所示:

public static void AddObject(EntityObject obj, string entitySetName)
{
    context.AddObject(entitySetName, obj);
    context.SaveChanges();
}
  • If I remove the line of code that manually sets the Cost when it reads the excel file, the save works fine. 如果我删除了读取Excel文件时手动设置Cost的代码行,则保存工作正常。
  • If I change the line of code to read Lists.Costs[2], it saves fine. 如果我将代码行更改为读取Lists.Costs [2],则可以节省罚款。
  • If I remove the line of code in GetNew() which sets the default, I get an error telling me that I violated the PK rule of CostTypes, meaning it's trying to insert the Cost Type. 如果删除设置默认值的GetNew()的代码行, GetNew()收到一条错误消息,告诉我我违反了CostTypes的PK规则,这意味着它正在尝试插入Cost Type。
  • Changing the ComboBox showing Type to something else still gives the same error. 将显示类型的ComboBox更改为其他内容仍会产生相同的错误。
  • After loading costs from the excel file, my regular Add/Edit forms throw the same error when I change the Type and try and save. 从excel文件加载费用后,当我更改“类型”并尝试保存时,我的常规“添加/编辑”表单会引发相同的错误。 If I don't load an excel file, they work fine. 如果我不加载excel文件,它们可以正常工作。

I'm still learning Entity Framework, but so far it has been nothing but a frustration and a headache to use. 我仍在学习Entity Framework,但到目前为止,它只是沮丧和令人头痛的使用。 Does someone know what my problem is and how I can fix it? 有人知道我的问题是什么以及如何解决?

EDIT 编辑

Here's the info requested by Slauma. 这是Slauma要求的信息。 I am keeping it simple and excluding unrelated objects 我保持简单,排除不相关的对象

  • Costs are in one table and CostTypes are in another table. Costs在一个表中,而CostTypes在另一个表中。 In the database, the Costs.TypeId column is not allowed to be null, and is a Foreign Key to CostTypes . 在数据库中, Costs.TypeId列不允许为null,并且是CostTypes的外键。 The Id field for both tables is auto-generated. 这两个表的Id字段都是自动生成的。

  • My EF model is just a generic one with the two database tables added. 我的EF模型只是添加了两个数据库表的通用模型。 The only change I made to it was to rename some fields and remove the CostTypes.Costs Navigation Property. 我对此所做的唯一更改是重命名了某些字段并删除了CostTypes.Costs导航属性。

  • The Excel file that gets imported maps most costs to their matching CostType.Name , however it IS possible that the string in the excel file doesn't match a CostType , so Lists.CostTypes.FirstOrDefault(t => t.Name == row[0].ToString()) can assign a NULL value to the Cost.Type property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a 导入的Excel文件将大多数成本映射到其匹配的CostType.Name ,但是excel文件中的字符串可能与CostType不匹配,因此Lists.CostTypes.FirstOrDefault(t => t.Name == row[0].ToString()) can assign a value to the Cost.Type property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a Lists.CostTypes.FirstOrDefault(t => t.Name == row[0].ToString()) can assign a NULL value to the property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a NULL CostType do not have an item selected in the CostType ComboBox` and trigger a validation error that must be corrected before saving. CostType do not have an item selected in the CostType property. That doesn't seem to be a problem though, because the form still comes up with the list of costs and their default selected items. Item's with a NULL CostType do not have an item selected in the CostType ComboBox中CostType do not have an item selected in the CostType并触发了验证错误,必须在保存之前纠正该错误。

The code to load the CostType list is 加载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();
    }
}

The ApplyOrder code can be found here . 可在此处找到ApplyOrder代码。

The GetList method is called from 从中调用GetList方法

public static class Lists
{
    public static List<CostType> CostTypes { get; private set; }

    static Lists()
    {
        CostTypes = DAL<CostEntities>.GetList<CostType>("Name");
    }
}

I figured it out.... it was a mix of a few different things 我想通了....这是一些不同的东西的混合

Creating a new Cost and setting the Type was adding the cost to the shared data context. 创建新Cost并设置Type会将成本添加到共享数据上下文中。 If that Cost wasn't included in the list of costs to save, or it failed it's validation error, or the user cancelled out of the Import dialog, the cost still existed in context.ObjectStateManager._addedObjects , even though I never called AddObject or AttachObject . 如果该成本未包含在要保存的成本列表中,或者它未能通过验证错误,或者用户从“导入”对话框中取消,则该成本仍然存在于context.ObjectStateManager._addedObjects ,即使我从未调用过AddObjectAttachObject Once I realized that I started callling DeleteObject on costs that were not going to be saved and it cleared up the 1st error I was getting. 一旦我意识到我开始对无法节省的成本调用DeleteObject ,并且清除了我遇到的第一个错误。

The 2nd error I was getting (duplicate PK) was because I was looping through my new Costs and calling AddObject and SaveChanges on each one. 我遇到的第二个错误(重复PK)是因为我在遍历新的Costs并在每个上调用AddObjectSaveChanges Since setting Cost.Type to an attached CostType was automatically adding my Cost to the context, the first cost to get saved was actually adding all the new Costs to the database while the 2nd cost was trying to call AddObject / SaveChanges on what EF saw as an object that already existed 由于将Cost.Type设置为附加的CostType会自动将我的Cost添加到上下文中,因此要保存的第一个成本实际上是将所有新的Costs添加到数据库中,而第二个成本则尝试在EF上调用AddObject / SaveChanges一个已经存在的对象

Here is not really a satisfying answer but a mix of guesses and open questions based on your infos in the question and in the comments to your question: 这并不是真正令人满意的答案,而是根据您在问题中的信息以及对问题的评论中的猜测和未决问题的组合:

  • First of all: Your list Lists.CostTypes contains obviously entities which are detached from the context where you are later adding and saving new objects in. Because you have a using block: using (var context = new TContext()) you are retrieving your CostType entities in another context. 首先:您的列表Lists.CostTypes显然包含与稍后要在其中添加和保存新对象的上下文分离的实体。因为您具有using块: using (var context = new TContext())您正在检索另一个上下文中的CostType实体。

  • To tell EF that these CostType entities already exist in the database you must attach the entities to your second context ( context.CostTypes.Attach(costType) ) where you save your changes in (or use the same context in your method where you retrieve the list). 要告诉EF这些CostType实体已经存在于数据库中,您必须实体附加到第二个上下文( context.CostTypes.Attach(costType) ),在其中保存更改(或在检索方法的方法中使用相同的上下文)列表)。 I don't see in your code that you do this. 我在您的代码中看不到您执行此操作。 ( CostType is a navigation reference property, not a foreign key property, right?) CostType是导航引用属性,而不是外键属性,对吧?)

  • On the other hand when the CostType entities are not attached you should get duplicated CostTypes in your database because EF will consider them as new objects (to insert in the DB) when you call AddObject for your Cost entity since EF will always put the whole object graph of detached entities into Added state. 另一方面,当未附加CostType实体时,您应该在数据库中获得重复的CostType,因为当您为Cost实体调用AddObject时,EF会将它们视为新对象(以便插入到数据库中),因为EF始终会将整个对象放入分离实体的图进入Added状态。 Do you get duplicated CostTypes in the DB in your working examples? 您在工作示例中是否在数据库中获得了重复的CostTypes? If not, something important is missing in your code snippets. 如果不是,则代码片段中缺少重要的内容。

  • The last paragraph assumes that the key for CostType is autogenerated in the DB, as you said. 如您所说,最后一段假定CostType的密钥是在数据库中自动生成的。 If not, you would get a PK constraint violation instead of duplicated entities. 如果没有,您将获得PK约束违规而不是重复的实体。

  • If the keys for CostType and Cost are really autogenerated identities, I am wondering where the PK violation you mentioned can come from. 如果CostTypeCost的键确实是自动生成的标识,我想知道您提到的PK违例来自何处。 Every insertion would create a new unique primary key. 每次插入都会创建一个新的唯一主键。 There could never a PK violaton occur. 永远不会出现PK紫罗兰。 Can you show the exception message in detail? 您可以详细显示异常消息吗?

  • Did you check that all Cost entities you want to save really have a non-null CostType property (after the user has fixed all validation errors)? 您是否检查过要保存的所有Cost实体确实具有非null的CostType属性(在用户修复了所有验证错误之后)? I cannot see any other possible reason in your code why you would get your "Relationship-could-not-be-changed-exception", except that at least for one of the Cost objects CostType is null . 我看不到任何其他可能的原因,为什么您会得到“无法更改的关系”例外,除非至少对于Cost对象之一CostTypenull

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM