Изображения в Lightswitch v3.0: Неверный URI: слишком длинная строка Uri.

У меня есть простой веб-клиент Lightswitch на базе Silverlight. Client.csproj и Server.csproj говорят, что LightSwitchVersion равно v3.0. Он работает на

  • Visual Studio 2012, обновление 4
  • Набор инструментов расширения LightSwitch для VS11
  • У меня 2 расширения, выбраны оба:

    • LightSwitch Cosmopolitan Shell and Theme
    • Расширения Microsoft LightSwitch

И у меня есть таблица MySQL

CREATE TABLE `images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `legend` varchar(200) NOT NULL,
  `preview` blob,
  `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

И я объявил поле preview как тип Image в источнике данных до того, как создал экран для таблицы. Но запущенное приложение встречает меня вот этим

Lightswitch 3.0 имеет проблемы с изображениями

С Lightswitch 2.0 все работает нормально. Но с тех пор, как я обновился до версии 3.0, это единственная проблема, которая все портит :-(


person Marcel    schedule 08.05.2015    source источник


Ответы (2)


Сам с этим не сталкивался, но интерес возник. :)

Похоже, что уровень OData использует содержимое столбца больших двоичных объектов для обеспечения параллелизма данных, и этот URI слишком длинный. В собственной таблице SQL Server вы можете просто добавить столбец Rowversion, и он будет выбран для целей параллелизма — встроенная база данных Lightswitch сделает это за вас автоматически. Насколько я понимаю, MySQL не имеет эквивалентного типа Rowversion.

Обходной путь состоит в том, чтобы создать еще один столбец в вашей таблице MySQL, который увеличивается триггером MySQL при каждом обновлении, что делает его полем параллелизма де-факто. Обновите источник данных, а затем отредактируйте файл .lsml, добавив в этот столбец атрибут <UseForConcurrency />.

Полное обсуждение находится на странице https://social.msdn.microsoft.com/Forums/vstudio/en-US/44581489-438d-4844-8194-0b4a0a41e56f/exception-invalid-uri-the-uri-string.-is-too-long?forum=lightswitch

person Phil    schedule 08.05.2015
comment
Кстати, переход с RIA на OData в качестве уровня данных был между Lightswitch 1.0 и 2.0. Возможно ли, что вы обновились с 1.0 до 3.0? - person Phil; 08.05.2015
comment
Я не уверен, но все мои *.csproj и *.lsproj имеют запись <LightSwitchVersion>v2.0</LightSwitchVersion>. Итак, я предполагаю, что начал с 2.0. - person Marcel; 09.05.2015
comment
Если вы не хотите изменять схему, вы можете предоставить базу данных MySQL в качестве поставщика Odata или подключиться к ней с помощью WCF-RIA - я предполагаю, что оба из них позволят избежать ошибки, но ни один из них не будет просто. Самое простое решение — вообще не обновлять проект и продолжать использовать рабочую версию. - person Phil; 11.05.2015
comment
Этот ответ содержит ключ к решению: <UseForConcurrency /> Но это далеко не работающее решение! Итак, я опубликовал свою полную реализацию для всех пользователей MySQL... - person Marcel; 21.05.2015

Вот мой подход к запуску полного зверя:

MySQL

Добавьте столбец для проверки параллелизма в таблицу MySQL: (Я решил использовать uuid(). Это самый простой способ получать уникальные значения каждый раз, когда я что-то меняю!)

-- The column itself.
ALTER TABLE images ADD COLUMN rowversion BINARY(16);
-- Setup for all existing rows.
UPDATE images SET rowversion = UNHEX(REPLACE(UUID(),'-',''));
-- Now make it NOT NULL.
ALTER TABLE images MODIFY COLUMN rowversion BINARY(16) NOT NULL;

-- An insert trigger to get a default value for future rows.
CREATE TRIGGER images_before_insert
  BEFORE INSERT ON images 
  FOR EACH ROW
  SET NEW.rowversion = UNHEX(REPLACE(UUID(),'-',''));

Выключатель

  1. Обновите источник данных.
  2. Сохраните все, закройте решение, откройте ..\Server\Properties\Service.lsml и просто добавьте <UseForConcurrency /> (и не больше) к записи rowversion (как сказал Фил). Теперь это может выглядеть
  <EntityProperty
    Name="rowversion"
    PropertyType=":Guid">
    <EntityProperty.Attributes>
      <UseForConcurrency />
      <Required />
      <NotSearchable />
    </EntityProperty.Attributes>
  </EntityProperty>

Но стоп, к сожалению, это НЕ ВСЕ! Этот злой Lightswitch не обновляет значение rowversion после сохранения. Таким образом, триггер BEFORE UPDATE ON images никогда не удовлетворит наши потребности. Поверьте, при каждом обновлении вы попадете в ад "Конфликт данных"!!! Вы должны изменить версию строки на стороне клиента:

public partial class ImageScreen
{
    partial void ImageScreen_Saving(ref bool handled)
    {
        var changes = DataWorkspace.testData.Details.GetChanges();

        foreach (var image in changes
            .ModifiedEntities
            .OfType<image>())
        {
            image.rowversion = Guid.NewGuid();
        }
    }
}

Теперь клиент теперь о последней версии строки, полученной от него самого. И если другой клиент изменит те же наборы данных, «Конфликт данных» будет объявлен правильно.

person Marcel    schedule 21.05.2015