Пользовательская сериализация / десериализация по полю с Entity Framework 4 - PullRequest
2 голосов
/ 30 сентября 2010

Я отвечаю за перевод нашего собственного DAL на решение на основе Entity Framework 4, но прежде чем я смогу это сделать, я должен быть уверен, что можно перевести все наши «конструкции» на эту новую технологию.

Одна из самых больших проблем, с которыми я сталкиваюсь, - это возможность прочитать поле и создать собственный тип. Допустимыми примерами могут быть битовая маска, сохраненная в поле BIGINT, список почтовых адресов, сохраненных в виде списка CSV в поле NVARCHAR, или поле XML, содержащее агрегированные данные, не имеющие своей собственной таблицы / объекта. В основном механизм сериализации не зафиксирован.

Давайте возьмем классический пример «Адрес».

public class Address
{
    public string Street {get; set;}
    public string City {get; set;}
    public string Zip {get; set;}
    public string Country {get; set;}
}

и давайте предположим, что мы хотим сохранить его в поле XML, используя этот шаблон:

<address>
  <street>Abrahamsbergsvägen, 73</street>
  <city>Stockholm</city>
  <zip>16830</zip>
  <country>Sweden</country>
</address>

Вопрос в основном таков: существует ли метод для переопределения того, как EF4 сериализует и десериализует содержимое поля, сопоставленного со свойством объекта?

Ответы [ 2 ]

2 голосов
/ 05 октября 2010

Я нашел это решение. Это не так чисто, как я хотел, но кажется, что ничего лучше не получается.

с учетом этой базовой сущности,

public class Institute
{
    public int InstituteID { get; set; }
    public string Name { get; set; }
    // other properties omitted
}

Я добавил в базу данных поле XML с именем Данные, содержащее несколько строк, используя этот простой шаблон

<values>
  <value>Value 1</value>
  <value>Value 2</value>
  <value>Value 3</value>
</values>

В объекте я добавил эти свойства и сопоставил поле базы данных «Данные» со свойством «DataRaw».

protected string DataRaw
{
    get
    {
        if (_Data == null)
            return _DataRaw;
        else
            return new XElement("values", from s in Data select new XElement("value", s)).ToString();
    }
    set
    {
        _DataRaw = value;
    }
}

private string _DataRaw;
private string[] _Data;

public string[] Data
{
    get
    {
        if (_Data == null)
        {
            _Data = (from elem in XDocument.Parse(_DataRaw).Root.Elements("value")
                     select elem.Value).ToArray();
        }
        return _Data;
    }

    set
    {
        _Data = value;
    }
}

Это решение работает. Вот пример кода:

class Program
{
    static void Main(string[] args)
    {
        var ctx = new ObjectContext("name=TestEntities");

        var institute = ctx.CreateObjectSet<Institute>().First();

        System.Console.WriteLine("{0}, {1}", institute.InstituteID, institute.Name);
        foreach (string data in institute.Data)
            System.Console.WriteLine("\t{0}", data);

        institute.Data = new string[] { 
            "New value 1",
            "New value 2",
            "New value 3"
        };

        ctx.SaveChanges();
    }
}

У кого-нибудь есть лучшее решение?

0 голосов
/ 02 октября 2010

Entity Framework НЕ сериализует и не десериализует объекты, а также не контролирует, как сериализация должна выполняться в других слоях или модулях вашего приложения.
Что вам нужно сделать, это просто открыть ваши POCO и добавить их Свойства с соответствующими атрибутами, которые будут учтены во время сериализации, когда вы захотите отправить их на другие уровни приложения.

...