You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MDriven批量插入B对象后Unload/Reload致关联A属性为空问题排查

MDriven中BulkInsert后Unload/Reload单关联属性为Null的问题

问题背景

模型关系为A 1 <==> n B,因B类对象数量庞大,直接调用UpdateDatabase()保存耗时过长,故采用BulkInsert批量存储B对象,A仍通过MDriven正常保存。为模拟MDriven的正常行为,需将B对象标记为clean,让后续操作识别其已保存状态,为此编写了MakeClean方法。

当前实现的MakeClean方法

/// <summary>
/// Makes a dirty object clean.
/// </summary>
/// <param name="ecoObject">EcoObjekt that will be made clean.</param>
public static void MakeClean(this IEcoObject ecoObject)
{
    var ecoServiceProvider = ecoObject.ServiceProvider();
    var classifier = ecoObject.AsIObject().UmlClass;
    var cache = ecoServiceProvider.GetEcoService<ICache>();
    var locator = ecoObject.AsIObject().GetLocator();

    cache.SetPersistenceState(locator, PersistenceState.Current);
    cache.SetExistenceState(locator, Cache.ExistenceState.Existing);

    foreach (var structuralFeature in classifier.AllStructuralFeatures.Cast<IStructuralFeature>().Where(x => x.Persistent))
    {
        cache.SetMemberPersistenceState(locator, structuralFeature, PersistenceState.Current);
    }
}

问题现象

通过以下代码卸载并重新加载B实例时:

var persistenceService = objectParameter.AsIObject().ServiceProvider.GetEcoService<IPersistenceService>();
persistenceService.Unload(objectParameter);

卸载操作会标记对象为"需重新加载",重新加载时出现异常:

  • 执行重载SQL能正常获取到A的外键值
  • MDriven无法定位到对应的A对象,错误地将单关联属性A设为null(实际A对象存在,且重载前已赋值)

已完成的检查

  • 模型与映射正确,使用UpdateDatabase()保存时,Unload/Reload功能正常
  • 自定义BulkInsert已正确保存数据,数据库中A对象的外键状态正常
  • 内部操作追踪(LogSql、LogSqlMeta、LogPMapper)未发现异常

追踪日志

Eco.Sql: 00:00:00.0050037: SELECT B.ID, B.ATTRIBUTE1, B.ATTRIBUTE2, B.A FROM B B WHERE B.ID = ?
Eco.SqlParams: 
 ID1=344 (System.Decimal) (DbType: Decimal)
Eco.PMapper: Fetched 1 objects of class B
Eco.PMapper: ApplyDataBlock
 Eco.PMapper: B.DefaultLoad : 1

测试用例(执行失败)

var ecoSpace = new EcoSpace();
var a = new A(ecoSpace) { ID = GetNextIDForA()};
var b = new B(ecoSpace)
{
    ID = GetNextIDForB(),
    A = a,
}

// 用MDriven原生保存的分支,此分支正常
// ecoSpace.UpdateDatabase();

// 自定义保存的分支,此分支失败
a.Save(); // 仅保存A(调用MDriven的UpdateDatabase(a)),B保持dirty状态

// 在此处设置断点,手动向数据库插入数据模拟BulkInsert
b.MakeClean(); // 调用上述MakeClean方法

b.Unload(); // 卸载B实例
Assert.IsNotNull(b.A); // 原生保存分支正常,自定义分支失败

额外信息

  • ORM映射通过自定义ORM文件实现,类与数据库为扁平1:1映射,无ECO_Type或TIMESTAMP列,ID通过自定义方法设置:
<ClassDef Name="B" >
    <AliasDef Name="B" Table="B" ExtentRequiresDiscriminator="False">
        <KeyImpl Name="EcoKey">
            <KeyColumn Name="ID" />
        </KeyImpl>
    </AliasDef>
    <KeyDef Name="EcoKey" Signature="System.Decimal" IsId="True" KeyMapper="Attribute" />
    <AttributeDef Name="ID" Columns="ID" />
    <SingleLinkDef Name="A" Columns="AID" Key="A.EcoKey" />
</ClassDef>
  • 创建B对象后,ObjectId格式如下,调用UpdateDatabase()后无变化:
136!D!AAEAAAD/////AQAAAAAAAAAEAQAAAA5TeXN0ZW0uRGVjaW1hbAQAAAAFZmxhZ3MCaGkCbG8DbWlkAAAAAAgICAgAAAAAAAAAAJ8BAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  • 调用IExternalIdService.ObjectForId(string id)可直接获取B对象,无需执行SQL,该行为与KeyMapper="Attribute"相关,无需从数据库回读ID,但仍存在Unload后A属性为空的问题。

请问MakeClean方法是否存在缺失?若存在,需补充哪些内容?若不存在,问题根源是什么?

内容的提问来源于stack exchange,提问作者Peter Buchmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:45:55