我有两个班级之间的主 - 细节关系。主类将包含许多详细信息的列表。目前我正在使用
public class Master: cloneable<T>
{
//other properties here...
private List<detailClass> details
public List<detailClass> Details
{
get { return details; }
}
}
在大师班里面。保存此类时,我需要在将数据表传递给sp之前使用数据表作为详细信息列表。 (因为我们在sql2008中使用表值参数)。使用tvp的原因是,1个主机可以包含超过10k的细节,而tvp是一种非常有效的方式,可以非常快速地将所有信息转储到数据库中。
Qs:当我将列表转换为数据表以进行数据库插入时,相同数据的内存使用量会增加一倍。除了直接使用数据表之外,还有更好的方法来保存master中的细节吗?
问:我接下来的选择是尝试使用List详细信息,并执行datatable.ImportRow(row)。但我不知道,如何在不定义任何列的情况下将数据添加到一行中。我也不知道任何外部对象如何能够在这样的列表中访问各个细节字段。
关注casperOne's answer我使用了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;
}
}
}
答案 0 :(得分:1)
您可以使用以下两种方法之一将结果传输到table-valued parameter:
IEnumerable<SqlDataRecord>
- 您可以在yield return
实施中使用IEnumerable<SqlDataRecord>
(或更简单的LINQ)来创建流媒体解决方案。DbDataReader
实现 - 您可以创建一个实现,该实现将引用您的列表,并在读者通过枚举时提供相应的转换。使用其中任何一个,您基本上可以创建实现,从列表中获取项目,然后将结果转换为表值参数。这样,您不必在应用程序中重新实现第二个列表,您可以根据需要在第一个列表上执行转换。
有关详细信息,请参阅标题为“Table-Valued Parameters in SQL Server 2008”的MSDN部分,特别是“配置SqlParameter示例”和“使用DataReader的Streaming Rows”部分。