• FormDataSource中Outer Join属性的一个Bug


    郁闷了一天,终于解决了一个问题,再次强烈鄙视Dynamics Ax的文档,很多很奇怪的用法一点文档介绍都没有!!
    问题描述:
    为了给InventSum表中每个ItemId和InventDimId的组合创建一个属性,又不改变这个表的结构,新建了一张名为InventSumProperty的表,字段描述如下:
    ItemId:料品Id
    InventDimId:库房维组Id
    Property:新增加的属性
    增加一个跟表InventSum的连接,连接字段为ItemId和InventDimId
    为了展示这些属性,新建了一个Form,由于需要显示某些物料和库存纬度的值,于是InventSum需要跟InventDim表内联,然后再跟InventSumProperty外联。
    这样这个Form就有三个数据源
    InventSum      JoinSource:空   LinkType:Delayed
    InventDim      JoinSource:InventSum      LinkType:InnerJoin
    InventSumProperty   JoinSource:InventSum   LinkType:OuterJoin
    将某些想展现的东东放到Grid里,本来以为万事大吉了,谁想到让俺着实郁闷了一把,打开窗体时迎接俺的是如下的错误:
    无法选择 InventSumExternal (InventSumExternal) 中的记录。该联接在 WHERE 子句中的联接表之间不包含任何链接。
    这个提示还真是莫名奇妙,不包含任何连接??明明在表InventSumExternal上加了连接啊......怪哉!
    排查过程
    以前做过蛮多三个表之间的内联,于是试着InventSumproperty的LinkType改成InnerJoin,果然这样就不报错了!但是这还是不能满足要求,因为如果改成InnerJoin,很多InventSum表中存在但在InventSumProperty中没有对应属性的值将不会显示,这不符合要求。
    看了一下是在执行InventSum_ds的ExcuteQuery方法时出错的,用SQL跟踪没有跟踪到任何语句,看来是在语句分析阶段就出错了,没有执行SQL语句。
    重载InventSum_ds的ExcuteQuery方法,在Super之前写入一下代码:
    info(InventSum_DS.query().dataSourceNo(1).toString());
    最终得到如下SQL语句
    SELECT * FROM InventSum 
    JOIN * FROM InventDim 
    WHERE InventSum.InventDimId = InventDim.inventDimId 
    OUTER JOIN * FROM InventSumExternal 
    WHERE InventSum.ItemId = InventSumExternal.ItemId AND InventSum.InventDimId = InventSumExternal.InventDimId
    这个语句应该是提交给SQL Server分析的语句,当然这个语句只是个半成品,在SQL Server中不能执行,在X++中也有语法错误。
    分别改装成真正的SQL版本和X++版本如下:
    SQL版本:
    SELECT * FROM InventSum 
    INNER JOIN  InventDim ON InventSum.InventDimId = InventDim.inventDimId 
    LEFT JOIN InventSumExternal ON InventSum.InventDimId = InventSumExternal.InventDimId
    上面这个语句在SQL Server运行没有任何问题
    X++版本:
    static void sqlTest(Args _args)
    {
        InventSum inventSum;
        InventDim inventDim;
        InventSumExternal inventSumExternal;
        ;
        
        SELECT 
    * FROM inventSum
            JOIN 
    * FROM inventDim
            WHERE InventSum.InventDimId 
    == InventDim.inventDimId
                 OUTER JOIN 
    * FROM inventSumExternal
                 WHERE InventSum.ItemId 
    == InventSumExternal.ItemId &&
                       InventSum.InventDimId 
    == InventSumExternal.InventDimId;

    }
    运行上面的语句,报出了与采用Form时一样的错!!看来问题出在这上面了,X++编译器在编译这个语句的时候有Bug,不能生成正确的SQL语句!郁闷死了......在这里卡壳了好半天,试来试去,突然想到把OUTER JOIN的顺序移到JOIN前面试试看。
    static void sqlTest(Args _args)
    {
        InventSum inventSum;
        InventDim inventDim;
        InventSumExternal inventSumExternal;
        ;
        
        SELECT 
    * FROM inventSum
            OUTER JOIN 
    * FROM inventSumExternal
                 WHERE InventSum.ItemId 
    == InventSumExternal.ItemId &&
                       InventSum.InventDimId 
    == InventSumExternal.InventDimId
                 JOIN 
    * FROM inventDim
                 WHERE InventSum.InventDimId 
    == InventDim.inventDimId;
     

    }
    ft!没想到这样就OK了!真是让人费解啊!
    如果能想办法让FormDataSource对应的Query生成的X++查询代码也是OUTERJOIN在前,INNERJOIN在后问题应该就解决了?试着将InventSumExternal_ds挪到InventDim_ds的前面,没有任何作用。。。。。。
    这个查询应该是在调用各个数据源的Init方法时构造出来的,前面测试过Init方法的执行顺序,当时还真是让人费解,貌似执行顺序不定,可能先执行这个,也可能后执行那个,并且与DataSource在Form中显示的次序没有关系。突然记起前面测试的时候先后创建的两个Form,用的是同样的两个数据源,结果两个数据源的Init方法调用的顺序正好相反,难道跟刚刚创建DataSource时的顺序有关???
    重新创建了一个Form,仍然使用上述三个DataSource,只不过在创建的时候按如下顺序
    InventSum,InventSumExternal,InventDim
    连接数据源和连接方式仍然按照前面的设定。
    NND,居然OK了!!
    彻底搞不懂了......
    结论:
    X++的解释器有bug,如果有两个数据源分别通过InnerJoin和OuterJoin关联到同一个数据源上,那么一定要记得在创建数据源的时候,连接关系为OuterJoin的数据源一定要先于InnerJoin的数据源创建。
    那位又问了?要是两个数据源都通过OuterJoin连接到同一个数据源该怎么办?
    您老就别难为AX了吧,恐怕这个它压根就没考虑,要不您试试看?
  • 相关阅读:
    小技巧-WEB API第一次加载很慢
    20165313 《Java程序设计》第一周学习总结
    spring-boot源码分析之BeanFactory · 叁
    spring-boot源码分析之BeanFactory · 贰
    aaa
    JavaScript FSO属性大全
    IE浏览器下用JS创建文件
    FileSystemObject详解
    HTTP状态码
    Spring中异步执行方法(@Async)
  • 原文地址:https://www.cnblogs.com/Farseer1215/p/627441.html
Copyright © 2020-2023  润新知