3

Допустим, у вас есть различные объекты произвольного типа, которые вы хотели бы сохранить в типе + значение типа таблицы. Ключ может быть, например, int, string или guid. Какова была бы ценность? Строка, двоичная или что-то еще?C#: Как вы можете хранить произвольные объекты в SQL Server?

И как вы храните и загружаете объекты? Я бы подумал о какой-то сериализации, но какой?


У меня есть одно решение в тот момент, когда у меня есть класс с этими двумя методами:

public T Get<T>(string key) 

public void Set<T>(string key, T value) 

В базе данных у меня есть таблица со столбцом строки и столбца двоичным. Затем я использую BinaryFormatter для сериализации и десериализации значения и Linq2Sql, чтобы поместить двоичный результат в таблицу базы данных. Но это хорошее решение? В настоящее время я только осмелился попробовать это с помощью простых значений, таких как целые числа и строки. Каким образом BinaryFormatter и сериализация в целом работают с более сложными типами, такими как structs и class? Особенно, если, например, значение содержит такие вещи, как массивы или списки.

Любые указатели?


В данный момент я буду использовать его для хранения различных значений, выбранных по-выбранному или напечатанному типу. Хотя они не всегда могут быть напечатаны. Например, он может выбирать значения из списка. Главное, что они будут в значительной степени просто удобными для пользователя, поэтому не очень важными данными.

+2

(И «Любые указатели» я не имею в виду «Должен ли я использовать какие-либо указатели») – Svish

+0

LOL. Указатели - возможно, хорошая идея, чтобы быть конкретными. –

ответ

6

Если вы можете ограничить себя конкретными типами, которые легко сопоставляются с типами SQL, у меня возникнет соблазн сохранить их в отдельных столбцах таблицы, убедившись, что вы заполняете только один из них. Таким образом, считываемых данных в базе данных, что упрощает временные запросы. Это также означает, что вы не навсегда заперты в .NET.

Доступны различные варианты сериализации. Основные каркасы - BinaryFormatter и XmlSerializer, конечно; XML гораздо более портативен, но стоит дорого. Я считаю, что он также менее тщательно настраивается.

Существуют сторонние технологии сериализации, такие как Thrift и Protocol Buffers. Они будут более ограничительными с точки зрения того, что они могут сериализовать), но более портативными. (Отказ от ответственности: мой 20-процентный проект - это C# port протокольных буферов, поэтому я не полностью объективен здесь.)

Вы также должны рассмотреть вопрос об управлении версиями - что вы хотите, если вы измените структуру данных, которую вы сериализуете/десериализации? Может быть, вам не нужно читать «старые» записи, может быть, и так. Возможно, вам нужен старый код, чтобы читать «новые» записи - или, может быть, нет.

Ваш выбор технологии должен действительно определяться требованиями. Чем более общим вы пытаетесь это сделать, тем сложнее это станет - так выработайте то, что вам действительно нужно, прежде чем пытаться придумать решение.

+0

Это очень верно. Добавляем к этому вопросу сценарий использования с более широкими возможностями. – Svish

+1

Вы прокомментировали использование в целом, но вам действительно нужно подумать о том, насколько вы счастливы ограничить себя. Чем меньше вам нужно, тем проще будет решение. –

1

Когда мы это сделали, мы сохранили данные в байтовом массиве в C# и сохранили его в столбце varbinary (max) в SQL Server.

EDIT Основываясь на комментарии

Вы могли бы попытаться иметь свойство на свой класс, который был массивом байт вашего поля значения.

+0

И, я думаю, вы использовали бы BinaryFormatter для преобразования из байтового массива в фактический объект? – Svish

+0

Имея свойство на моем классе, который является массивом байтов, может работать, я думаю. Это означает, что класс будет обрабатывать сериализацию, верно? – Svish

0

Обычно я использую определенный столбец для определенного значения.

Например.

  • Guid: UNIQUEIDENTIFIER
  • номера, как int, decimal, byte и т.д.: DECIMAL
  • string: NVARCHAR
  • DateTime: DATETIME

Я использую NHibernate, там очень легко иметь подклассу s для каждого конкретного типа и сопоставить их с одной и той же таблицей, каждый из которых использует определенное поле для своего конкретного значения. Я получаю таблицу, как это:

create table dbo.Value (
    Name NVARCHAR(80) not null, 
    Type NVARCHAR(6) not null, 
    TextValue NVARCHAR(500) null, 
    GuidValue UNIQUEIDENTIFIER null, 
    NumericValue DECIMAL(36, 18) null, 
    DateTimeValue DATETIME null 
) 

Тип Столбец либо 'TEXT', 'GUID', 'NUMBER' или 'ДАТА'. Это все сделано NHibernate, но его можно легко использовать и манипулировать без него.

Кроме того, вы можете сохранить ссылку на другой объект, используя тип NH any как значение (сохранение первичного ключа и имя объекта).

+0

Может ли что-то подобное сделать с Linq2Sql? – Svish

+0

Не знаю, я его не использую. На самом деле, я сомневаюсь, потому что Linq2Sql, насколько я знаю, не ORM, поэтому вы, скорее всего, не сможете наследовать в одной таблице. Или, конечно, вы можете смоделировать эту же таблицу, но ваши запросы выполняются непосредственно на этой плоской структуре. Вы увидите все столбцы, даже если используется только один из них. –

Смежные вопросы