WCF Data Services Expand ведет себя неожиданно при задании определенных размеров страницы сущности

При подготовке нашей службы данных WCF к производству мы столкнулись с проблемой с поведением оператора расширения при включенном разбиении по страницам.

Если разбиение по страницам отключено, расширение работает должным образом. Но когда я включаю разбиение на страницы для любого из расширенных наборов объектов, независимо от размеров страницы, развернутые объекты отображаются на странице с размером 1.

[ОБНОВЛЕНИЕ]

В отсутствие каких-либо дополнительных сведений отсюда или форумов MSDN я создал ошибка при подключении. Может, кто-нибудь через стену докопается до сути!

Например, предположим, что у меня есть следующая простая модель: Example Model

Он работает в сгенерированной базе данных SQL с некоторыми примерами данных:

INSERT INTO [dbo].[Towns] (Name) VALUES ('Berlin');
INSERT INTO [dbo].[Towns] (Name) VALUES ('Rome');
INSERT INTO [dbo].[Towns] (Name) VALUES ('Paris');

INSERT INTO [dbo].[Gentlemen] (Id, Name) VALUES (1, 'Johnny');

INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Frieda', 'Berlin', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Adelita', 'Berlin', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Milla', 'Berlin', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Georgine', 'Paris', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Nannette', 'Paris', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Verona', 'Rome', 1);
INSERT INTO [dbo].[Ladies] (Name, Town_Name, Gentleman_Id) VALUES ('Gavriella', 'Rome', 1);

Служба данных проста (обратите внимание, что здесь отключена подкачка):

namespace TestWCFDataService
{
    public class TestWCFDataService : DataService<TestModel.TestModelContainer>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("Ladies", EntitySetRights.AllRead);
            config.SetEntitySetAccessRule("Gentlemen", EntitySetRights.AllRead);
            config.SetEntitySetAccessRule("Towns", EntitySetRights.AllRead);

            //config.SetEntitySetPageSize("Ladies", 10);
            //config.SetEntitySetPageSize("Gentlemen", 10);
            //config.SetEntitySetPageSize("Towns", 10);

            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }
}

Теперь мой пользователь хочет найти всех Lady, Town которых - "Берлин", а также их Gentleman.

Рассматриваемый запрос:

http://localhost:62946/TestWCFDataService.svc/Towns('Berlin')?$expand=Ladies/Gentleman

Когда я запускаю этот запрос (JSON, потому что версия Atom гигантская), я получаю ожидаемый результат; город с тремя дамами, джентльменами каждой из которых является Джонни.

var result = {
        "d": {
            "__metadata": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Towns('Berlin')", "type": "TestModel.Town"
            }, "Name": "Berlin", "Ladies": [
    {
        "__metadata": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(1)", "type": "TestModel.Lady"
        }, "Id": 1, "Name": "Frieda", "Gentleman": {
            "__metadata": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)", "type": "TestModel.Gentleman"
            }, "Id": 1, "Name": "Johnny", "Ladies": {
                "__deferred": {
                    "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)/Ladies"
                }
            }
        }, "Town": {
            "__deferred": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(1)/Town"
            }
        }
    }, {
        "__metadata": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(2)", "type": "TestModel.Lady"
        }, "Id": 2, "Name": "Adelita", "Gentleman": {
            "__metadata": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)", "type": "TestModel.Gentleman"
            }, "Id": 1, "Name": "Johnny", "Ladies": {
                "__deferred": {
                    "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)/Ladies"
                }
            }
        }, "Town": {
            "__deferred": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(2)/Town"
            }
        }
    }, {
        "__metadata": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(3)", "type": "TestModel.Lady"
        }, "Id": 3, "Name": "Milla", "Gentleman": {
            "__metadata": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)", "type": "TestModel.Gentleman"
            }, "Id": 1, "Name": "Johnny", "Ladies": {
                "__deferred": {
                    "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)/Ladies"
                }
            }
        }, "Town": {
            "__deferred": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(3)/Town"
            }
        }
    }
    ]
        }
    }

В конечном итоге их будет много Towns, поэтому я включаю пейджинг для города.

...
            config.SetEntitySetPageSize("Towns", 10);
...

Запрос продолжает функционировать, как ожидалось. Но также будет много Ladies и Gentlemen, поэтому я хочу иметь возможность ограничить количество возвращаемых результатов:

...
            config.SetEntitySetPageSize("Ladies", 10);
            config.SetEntitySetPageSize("Gentlemen", 10);
...

Но когда я устанавливаю размер страницы либо для набора сущностей Ladies, либо для набора сущностей Gentlemen (или обоих), результаты моего запроса неожиданно меняются:

var result = {
    "d": {
        "__metadata": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Towns('Berlin')", "type": "TestModel.Town"
        }, "Name": "Berlin", "Ladies": {
            "results": [
{
    "__metadata": {
        "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(1)", "type": "TestModel.Lady"
    }, "Id": 1, "Name": "Frieda", "Gentleman": {
        "__metadata": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)", "type": "TestModel.Gentleman"
        }, "Id": 1, "Name": "Johnny", "Ladies": {
            "__deferred": {
                "uri": "http://localhost:62946/TestWCFDataService.svc/Gentlemen(1)/Ladies"
            }
        }
    }, "Town": {
        "__deferred": {
            "uri": "http://localhost:62946/TestWCFDataService.svc/Ladies(1)/Town"
        }
    }
}
]
        }
    }
}

Расширение включает только один из объектов Леди (хотя включен, по крайней мере, ее Джентльмен). Неважно, насколько велик установлен размер страницы, запрос по-прежнему возвращает только один объект в расширенной коллекции.

Также не имеет значения, установлен ли размер страницы для одного или обоих развернутых объектов, если для одного из них задан размер страницы, то только один из Lady объектов будет загружен без промедления.

Такое поведение кажется мне ошибочным, поскольку согласно спецификации OData:

«URI с параметром системного запроса $ expand указывает, что записи, связанные с записью или коллекцией записей, идентифицированной разделом« Путь к ресурсам »URI, должны быть представлены встроенными (т. Е. Быстро загруженными)».

Я неправильно читаю спецификацию? Должен ли я ожидать такого поведения? Я просто хочу иметь возможность ограничивать размер страницы наборов сущностей при прямом доступе, но также иметь возможность загружать их.

Это ошибка в службах данных WCF? (или мой код? или мой мозг?)

[РЕДАКТИРОВАТЬ]

Дополнительная информация: в документации для служб данных WCF говорится, что:

«Кроме того, когда в службе данных включена подкачка, вы должны явно загружать последующие страницы данных из службы».

Но я не могу найти объяснения, почему размер страницы для связанных наборов сущностей, по-видимому, по умолчанию равен 1, независимо от того, какой размер страницы указан.

[РЕДАКТИРОВАТЬ]

Еще больше информации: рассматриваемая версия находится на .NET 4 версии 4.0.30319 с System.Data.Services версией 4.0.0.0. Это версия, которая идет в комплекте с Visual Studio 2010 (с установленным SP1).

[РЕДАКТИРОВАТЬ]

Пример решения, демонстрирующего поведение, теперь находится в репозитории github. В нем включена разбивка на страницы в методе InitializeService и в сценарии создания БД, который также добавляет некоторые образцы данных, так что мы находимся на одной странице.


person Jeffy    schedule 10.05.2011    source источник
comment
На форумах MSDN было небольшое обсуждение, где я опубликовал эту проблему после того, как получил очень мало ответа. Я обновлю этот вопрос, когда дойду до сути, но оставлю его здесь, потому что чем больше глаз, тем лучше IMO.   -  person Jeffy    schedule 13.05.2011


Ответы (3)


Прошло несколько месяцев, но это очевидно будет исправлено в следующей версии:

Размещено Microsoft 15.12.2011, 8:08

Спасибо, что сообщили об этой проблеме. Мы подтвердили, что ошибка в Entity Framework вызывает эту проблему. Исправление потребовало изменений в основных компонентах Entity Framework, поставляемых в .NET Framework. Мы исправили ошибку, исправление будет включено в следующий выпуск .NET Framework.

person Jeffy    schedule 31.03.2012

Какую версию WCF Data Services вы используете? Я обнаружил ошибку, связанную с использованием Expand с управляемым сервером разбиением по страницам в .NET Framework 4, но я думал, что это влияет только на сущности с составными ключами и при использовании параметра OrderBy, ни один из которых, похоже, здесь не применим. Тем не менее, это определенно похоже на ошибку.

Вы пробовали использовать Atom вместо JSON, и если да, то все еще отсутствуют объекты в раскрытии?

person Glenn Gailey - MSFT    schedule 10.05.2011
comment
.NET 4 из последнего пакета обновления. На самом деле мы обычно используем Atom для этого, я просто использовал JSON для публикации примера, потому что он более краткий. - person Jeffy; 10.05.2011

Ваш запрос: localhost: 62946 / TestWCFDataService.svc / Towns ('Berlin')? $ Expand = Ladies / Gentleman

не расширяет Дамы, только Gentelman.

Запрос должен выглядеть так:

localhost: 62946 / TestWCFDataService.svc / Towns ('Берлин')? $ expand = Дамы, дамы / джентльмены.

Надеюсь это поможет!

Моника Фринту

person Monica    schedule 10.05.2011
comment
Расширение Ladies/Gentlemen также раскрывает Ladies. Такое поведение задокументировано (хотя и нечетко) в спецификации OData (см. второй пример $expand), и если изменить запрос, как вы описали, результаты будут такими же. - person Jeffy; 11.05.2011