breezejs - 引用同一父级的导航属性之间的冲突

时间:2013-09-02 07:18:54

标签: breeze

我遇到过一个问题,即如果两个子实体都与单个父实体相关,那么导航属性并不总是得到正确解析 - 它似乎取决于实体加载的顺序。

我在版本1.4.1中注意到了这一点。我以前在1.3.5,一切都很好。

代码示例可能更好地显示了这一点:

<!DOCTYPE html>
<html>
<head>
    <title></title>

    <script src="../app/scripts/vendor/custom.modernizr.js"></script>
    <script src="../app/scripts/vendor/jquery.js"></script>
    <script src="./jquery.mockjax.js"></script>

    <script src="../app/components/node-uuid/uuid.js"></script>
    <!-- breeze and dependencies -->
    <script src="../app/components/q/q.min.js"></script>
    <script src="../app/components/breeze/Breeze.Client/Scripts/breeze.debug.js"></script>

    <script>
        var dataservice = new breeze.DataService({
            serviceName: '/api', // the URL endpoint
            hasServerMetadata: false // the service won't give us metadata
        });
        var DT = breeze.DataType; // alias

        function defaultInitializer (entity) {
            setId(entity);
        }

        function setId(entity) {
            if (!(entity.id)) {
                entity.id = uuid();
            }
        }

        function Parent() { }
        function Child() { }
        function ProblemChild() { }

        //#region private members
        function initialize(metadataStore) {

            var namespace = 'Namespace';

            metadataStore.addEntityType({
                shortName: 'Parent',
                namespace: namespace,
                dataProperties: {
                    id: { dataType: DT.Guid, isPartOfKey: true },
                    name: { dataType: DT.String }
                },
                navigationProperties: {
                    children: {
                        entityTypeName:  'Child:#'+namespace,
                        isScalar: false,
                        associationName: 'Parent_Child'
                    },
                    problemChildren: {
                        entityTypeName:  'ProblemChild:#'+namespace,
                        isScalar: false,
                        associationName: 'Parent_Problem_Child'
                    }
                }
            });
            metadataStore.addEntityType({
                shortName: 'Child',
                namespace: namespace,
                dataProperties: {
                    id: { dataType: DT.Guid, isPartOfKey: true },
                    parentId: { dataType: DT.Guid },
                    name: {dataType: DT.String}
                },
                navigationProperties: {
                    parent: {
                        entityTypeName: 'Parent:#'+namespace,
                        isScalar: true,
                        associationName: 'Parent_Child',
                        foreignKeyNames: ['parentId']
                    }
                }
            });
            metadataStore.addEntityType({
                shortName: 'ProblemChild',
                namespace: namespace,
                dataProperties: {
                    id: { dataType: DT.Guid, isPartOfKey: true },
                    parentId: { dataType: DT.Guid },
                    name: {dataType: DT.String}
                },
                navigationProperties: {
                    parent: {
                        entityTypeName: 'Parent:#'+namespace,
                        isScalar: true,
                        associationName: 'Parent_Problem_Child',
                        foreignKeyNames: ['parentId']
                    }
                }
            });

            metadataStore.registerEntityTypeCtor('Parent', Parent, defaultInitializer);
            metadataStore.registerEntityTypeCtor('Child', Child, defaultInitializer);
            metadataStore.registerEntityTypeCtor('ProblemChild', ProblemChild, defaultInitializer);
        }

        var model = {
            initialize: initialize
        };

        var manager = new breeze.EntityManager({dataService: dataservice});
        model.initialize(manager.metadataStore);

        var parent = manager.createEntity('Parent', {name: 'Tony'});
        var child = manager.createEntity('Child', {name: 'Tony Jr'});
        var problemChild = manager.createEntity('ProblemChild', {name: 'Problem Tony Jr'});

        child.parentId = parent.id;
        problemChild.parentId = parent.id;

        console.log('Created manually');
        console.log(child.name, 'has a parent:', !!child.parent);
        console.log(problemChild.name, 'has a parent:', !!problemChild.parent);
        console.log(parent.name, 'has a child:', !!parent.children[0]);
        console.log(parent.name, 'has a problem child:', !!parent.problemChildren[0]);

        manager.clear();

        var ctor = function () {
            this.name = "mock";
            this.defaultSettings = { };
        };

        ctor.prototype.initialize = function () {
        };

        ctor.prototype.ajax = function (settings) {
            jQuery.ajax(settings);
        };

        breeze.config.registerAdapter("ajax", ctor);
        breeze.config.initializeAdapterInstance("ajax", "mock", /*isDefault = */ true);

        $.mockjax({
            url: '/api/all',
            responseTime: 0,
            responseText: {
                Entities: [
                    {
                        "id": "3",
                        "name": "Problem Jr (right)",
                        "parentId": "1",
                        $type: "ProblemChild:#Namespace"
                    },
                    {
                        "id": "1",
                        "name": "Tony (right)",
                        $type: "Parent:#Namespace"
                    },
                    {
                        "id": "2",
                        "name": "Tony Jr (right)",
                        "parentId": "1",
                        $type: "Child:#Namespace"
                    }
                ]
            }
        });

        var resourceName = 'all';
        var query = new breeze.EntityQuery().from(resourceName);
        manager.executeQuery(query)
                .then(function () {
                    parent = manager.getEntities('Parent')[0];
                    child = manager.getEntities('Child')[0];
                    problemChild = manager.getEntities('ProblemChild')[0];
                    console.log('\nLoaded in parent-child order');
                    console.log(child.name, 'has a parent:', !!child.parent);
                    console.log(problemChild.name, 'has a parent:', !!problemChild.parent);
                    console.log(parent.name, 'has a child:', !!parent.children[0]);
                    console.log(parent.name, 'has a problem child:', !!parent.problemChildren[0]);
                })
                .then(function () {
                    manager.clear();
                    $.mockjaxClear();
                    $.mockjax({
                        url: '/api/all',
                        responseTime: 0,
                        responseText: {
                            Entities: [
                                {
                                    "id": "3",
                                    "name": "Problem Jr (wrong)",
                                    "parentId": "1",
                                    $type: "ProblemChild:#Namespace"
                                },
                                {
                                    "id": "2",
                                    "name": "Tony Jr (wrong)",
                                    "parentId": "1",
                                    $type: "Child:#Namespace"
                                },
                                {
                                    "id": "1",
                                    "name": "Tony (wrong)",
                                    $type: "Parent:#Namespace"
                                }
                            ]
                        }
                    });
                    return manager.executeQuery(query);
                })
                .then(function () {
                    parent = manager.getEntities('Parent')[0];
                    child = manager.getEntities('Child')[0];
                    problemChild = manager.getEntities('ProblemChild')[0];
                    console.log('\nLoaded in child-parent order');
                    console.log(child.name, 'has a parent:', !!child.parent);
                    console.log(problemChild.name, 'has a parent:', !!problemChild.parent);
                    console.log(parent.name, 'has a child:', !!parent.children[0]);
                    console.log(parent.name, 'has a problem child:', !!parent.problemChildren[0]);
                })
                .fail(function () {
                    console.log('fail', arguments);
                });


    </script>
</head>
<body>
</body>
</html>

如果您加载此页面(您需要获取https://github.com/appendto/jquery-mockjax),那么您应该获得以下控制台输出:

Created manually breeze
Tony Jr has a parent: true breeze
Problem Tony Jr has a parent: true
Tony has a child: true
Tony has a problem child: true
MOCK GET: /api/all 
Object {url: "/api/all", type: "GET", isLocal: false, global: true, processData: true…}
 jquery.mockjax.js:530

Loaded in parent-child order
Tony Jr (right) has a parent: true
Problem Jr (right) has a parent: true
Tony (right) has a child: true
Tony (right) has a problem child: true
MOCK GET: /api/all 
Object {url: "/api/all", type: "GET", isLocal: false, global: true, processData: true…}
 jquery.mockjax.js:530

Loaded in child-parent order
Tony Jr (wrong) has a parent: false
Problem Jr (wrong) has a parent: true
Tony (wrong) has a child: false
Tony (wrong) has a problem child: true

最后一个例子证明了这个问题,其中改变加载数据的顺序意味着'Tony Jr'没有父母,而'Tony'没有孩子。 (两者都应该是假的。)

如何解决此问题?

0 个答案:

没有答案