Linq-To-Sql ORM 更新一对多

Posted

技术标签:

【中文标题】Linq-To-Sql ORM 更新一对多【英文标题】:Linq-To-Sql ORM Update One To many 【发布时间】:2020-07-28 17:42:21 【问题描述】:

我正在努力使用 Linq-to-sql Orm 同时更新多条记录。 我制作的数据库如下: 一份招标有一个或多个细节。 一个 TenderingDetails 有一个或多个 DetailsOptions。 一个选项有一个或多个 ConfigDetail。

我能够正常使用 Linq To Sql 创建那些。

但是当我尝试更新时,我最终有多个记录。 我为上述每个实体都有一个模型类,然后我传递给更新 Tindering、TinderingDetails、DetailsOptions 和 OptionConfigDetails 实体的服务

然后当我尝试更新如下:

the parameters are :
                TenderingModel tenderingModel,
                TenderingDetailsModel tenderingDetailModel,
                List<TenderingOption> optionsList
try

     var entity = ModelMapper.GetTenderingEntity(TenderingModel);
     //The next statement is where i got form dataconetxt ->singleordefault 
     //then map the properties one by one
     _unitOfWork.TenderingRepository.Update(entity);
     var tenderingDetailEntity = ModelMapper.GetTenderingDetailEntity(tenderingDetailModel)
    _unitOfWork.TenderingDetailsRepository.Update(tenderingDetailEntity);
    //Update Options
     if (optionsList != null)
                
                    var optionsEntities = new List<OptionItem>();
                    optionsList.ForEach(o =>
                    
                    //Just get the Entity from the model
                        optionsEntities.Add(o.GetEntity());
                    );

                    foreach (var item in optionsEntities)
                    
                        item.ID_Tendering_DETAILS = pricingDetailEntity.ID_Tendering_DETAILS;
                        //Delete the exisiting and config details
                       
                        //delete all configuration details
                        _unitOfWork.OptionConfigurationsRepository.DeleteAllByOptionId(item.ID_OPTION);
                        
                        //Add the new  Config Details
                       
                        item.OptionConfigurationDetails.ToList().ForEach(od =>
                        

                            _unitOfWork.OptionConfigurationsRepository.Create(od);
                        );

                        _unitOfWork.OptionsRepository.Update(item);
                    

                
                //this mainly would submitChanges()
                _unitOfWork.Commit();

catch (Exception e)
        

            throw new Exception($"Error while Updating  the Tendering, details are : e.Message");
        

我期待的是我将更新如下:

TenderingDetail 实体将由模型中的值更新, 作为 Tendering Detail 的子选项的选项将通过删除其所有配置详细信息来更新, 然后在更新选项表本身的同时添加新的 但发生的情况是我会得到选项和详细信息的添加记录,而不是更新???

编辑:

这似乎是我使用的更新方法做错了,但我不知道它到底是什么: 例如招标表有以下列:

Id -> Primary Key
ClientId-> FK
Current Revision -> int value, nullable
some other column values that are having default values , like time stamps , and etc,

我是如何更新的,比如:

public void Update(Tendering tendering)
        
           var tenderingEntity =  GetTendering ById(pricing.ID_Tendering);

            tenderingEntity .CURRENT_REVISION = tendering.CURRENT_REVISION;
            tenderingEntity .ID_CLIENT = tendering.ID_CLIENT;               
        

【问题讨论】:

你有主键吗?当您拥有主键时,现有项目会更新(不重复)。当您没有主键时,可能会发生重复。假设数据库中有两行苹果,数量分别为 10 和 20。如果将数量更新为 15,会发生什么情况? 是的,我确实有主键:每个表都有自己的主键,然后我为一对多关系创建外键 实体包含映射到数据库中表的类。首先确保映射正确。人们经常更改数据库中的列,然后忘记刷新映射。当您查询数据库时,会填充 c# 中的类。然后,当您更新更改的类中的数据时,会将其放回数据库中。如果您在类中添加行,则会出现问题。来自查询的原始数据被映射到数据库表中的行。但是当添加新行时,事情可能会变得一团糟。 我做了一个简短的编辑,你能看一下吗? 我通常使用 if (optionsList.Count() > 0) 因为它可以是零而不是 null。 TenderingModel的这两个参数是哪里来的tenderingModel,TenderingDetailsModel,tenderingDetailModel,你更新了数据库所以不确定这两个参数是不是跟数据库同步了。 【参考方案1】:

根据提供的代码,我不确定这里的 _unitOfWork 是什么,或者您如何处理您的数据库上下文。通常,当保存重复记录时,当使用不同的上下文来保存父项和子项或从您尝试保存的上下文之外的上下文中获取项目时,就会发生这种情况。仔细检查您的存储库和工作单元的实现,以确保它们在操作结束时发出单个 Save,并且所有值都由同一个上下文实例获取和保存。

顺便说一句,您的 _UnitOfWork 感觉更像是一个活动记录模式,而不是一个真正的工作单元。

【讨论】:

以上是关于Linq-To-Sql ORM 更新一对多的主要内容,如果未能解决你的问题,请参考以下文章

三大框架 之 Hibernate查询(一对多多对多查询关系)

laravel ORM 一对一 一对多 多对多 原生的MYSQL怎么写

Laravel5.6 Eloquent ORM 关联关系,一对一和一对多

ORM多表操作之一对多查询之对象查询

减少 MySQL 中具有许多一对多关系 (ORM) 的查询

在 ORM(Eloquent)中,具有 Genre 的 Book 是一对多关系吗?