Использование списка датаров для хранения данных - PullRequest
2 голосов
/ 23 августа 2010

У меня есть отношения мастер-детали между 2 классами.Мастер-класс будет содержать список многих деталей.В настоящее время я использую

public class Master: cloneable<T>
{
     //other properties here...
    private List<detailClass> details
    public List<detailClass> Details
    {
        get { return details; }
    }
}

внутри мастер-класса.При сохранении этого класса мне нужно использовать таблицу данных для списка деталей, прежде чем передать его в sp.(поскольку мы используем параметры табличных значений в sql2008).причина использования tvp заключается в том, что 1 мастер может содержать более 10 тыс. деталей, а tvp - очень эффективный способ очень быстрой передачи всей этой информации в БД.

Qs: Когда я преобразую список в таблицу данныхдля вставки БД используется двойная память для тех же данных.Есть ли лучший способ сохранить детали в master, кроме прямого использования данных?

В: Следующий вариант - попытаться использовать детали списка и выполнить datatable.ImportRow (row).Но я не знаю, как я могу добавить данные в строку, не определяя столбцы.Я также не знаю, каким образом любой внешний объект может получить доступ к отдельным полям сведений в таком списке.


После ответа casperOne Я использовал метод IEnumerable<SqldataRecord> и смог вставить данныепутем потоковой передачи и без необходимости создания дополнительной таблицы данных в памяти. Чтобы быть полезным для всех, кто ищет подобное решение, я публикую код ниже.

public class DetailCollection: List<Detail>, IEnumerable<SqlDataRecord>
{
    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator()
    {
        // mapping the properties of the Detail object to the 
        // user defined table type in sql
        SqlMetaData[] metaDataArray = new SqlMetaData[4];

        //-1 indicates varchar(max) sql data type
        metaDataArray[0] = new SqlMetaData("Col1", SqlDbType.VarChar, -1); 
        metaDataArray[1] = new SqlMetaData("Col2", SqlDbType.TinyInt);
        metaDataArray[2] = new SqlMetaData("Col3", SqlDbType.VarChar,100);
        metaDataArray[3] = new SqlMetaData("Col4", SqlDbType.Int);

        SqlDataRecord sdr = new SqlDataRecord(metaDataArray);


        foreach (Detail detailRecord in this)
        {
                    sdr.SetValue(0, detailRecord.Property1);
                    sdr.SetValue(1, Convert.ToByte(detailRecord.Property2));
                    sdr.SetValue(2, detailRecord.Property3);
                    sdr.SetValue(3, detailRecord.Property4);
                    yield return sdr;
        }
    }
}

1 Ответ

1 голос
/ 23 августа 2010

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

  • IEnumerable<SqlDataRecord> - Вы можете использовать yield return в реализации IEnumerable<SqlDataRecord> (или LINQ, что еще проще) для создания потокового решения.
  • DbDataReader реализация - Вы можете создать реализацию, которая будет принимать ссылку на ваш список и предоставлять соответствующие преобразования при перечислении читателя.

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

Дополнительные сведения см. В разделе MSDN под названием « Табличные параметры в SQL Server 2008 », в частности в разделах «Пример настройки SqlParameter» и «Потоковые строки с помощью DataReader».

...