var store = GetStore(); 使用(IsolatedStorageFileStream fileStream = store.OpenFile(RootData,FileMode.Create)) { DataContractSerializer serializer = new DataContractSerializer(typeof(List)); serializer.WriteObject(fileStream,rootdatalist); }
但这只是序列化了rootdatalist,而不是子项目。 rootdatalist有一个节点List属性,我该如何序列化它,以便我得到列表层次结构序列化?
由于它是dbml生成的对象,因此Root的Nodes属性为
public System.Data.Linq.Table<Node> Nodes
{
get
{
return this.GetTable<Node>();
}
}
我的Datacontext返回是:
public List<Root> GetRootList(Guid userid)
{
DataLoadOptions loadopts = new DataLoadOptions();
loadopts.LoadWith<Root>(s => s.Nodes);
this.DataContext.LoadOptions = loadopts;
return this.DataContext.Root.Where(s => s.Nodes.Count(n => n.UserId == userid) > 0).ToList();
}
节点实体集在我的dbml designer
中看起来如下[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Root_Node", Storage="_Nodes", ThisKey="Id", OtherKey="RootId")]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=5, EmitDefaultValue=false)]
public EntitySet<Node> Nodes
{
get
{
if ((this.serializing && (this._Nodes.HasLoadedOrAssignedValues == false)))
{
return null;
}
return this._Nodes;
}
set
{
this._Nodes.Assign(value);
}
}
此外,我必须在我的属性上方添加[Include]
标记,否则不会加载任何内容。
编辑::
对于想要序列化dbml类http://blogs.msdn.com/b/wriju/archive/2007/11/27/linq-to-sql-enabling-dbml-file-for-wcf.aspx
答案 0 :(得分:9)
您能否包含有关合约类型的更多信息?例如,我希望期望将Root
标记为数据合同,并将该成员作为数据成员,例如:
[DataContract]
public class Root {
[DataMember]
public List<SubItem> Nodes {get;private set;}
}
[DataContract]
public class SubItem {
[DataMember]
public int Foo {get;set;}
[DataMember]
public string Bar {get;set;}
}
那应该有用。如果没有,那么查看你的类型(或者它们的简化版本,这说明了问题)真的很有帮助。
答案 1 :(得分:7)
DataContractSerializer
需要了解对象图中所有类型的内容。
使用constructor overload,您可以指定这些以及根类型:
DataContractSerializer serializer = new DataContractSerializer(typeof(List<Root>), listOfOtherTypes);
答案 2 :(得分:0)
行;我再次使用Person
/ PersonPhone
表(在Person
模式中)从新的AdventureWorks2008R2安装中重现了这一点。
我将数据上下文设置为“单向”序列化,使用标准的LINQ-to-SQL绑定等(无需自定义)。
要与您的方案进行比较,Person
可以有PersonPhone
个,我们对List<Person>
感兴趣。我查看了3个场景,每个场景都在查看完整的数据集:
Person
条记录LoadWith
获取电话记录结果如下;正如你所看到的,1以你描述的方式失败,但2&amp; 3工作正常,区别在于3 显着更多TSQL工作。
所以没有进一步的细节(理想情况下是一个完全可重现的例子),非常很难进一步调查......
结果:
Default
=======
Bytes: 20219898
Original person count: 19972
Original phone count: 0
Deser person count: 19972
Deser phone count: 0
Log: 1140
LoadWith
========
Bytes: 24767996
Original person count: 19972
Original phone count: 19972
Deser person count: 19972
Deser phone count: 19972
Log: 2517
Enumerated
==========
Bytes: 24767996
Original person count: 19972
Original phone count: 19972
Deser person count: 19972
Deser phone count: 19972
Log: 6322697
试验台:
class Program
{
static void Main(string[] args)
{
using(var dc = new DataClasses1DataContext())
{ // 1: vanilla
dc.Log = new StringWriter();
RoundtripAndCount("Default", dc.Persons);
Console.WriteLine("Log: " + dc.Log.ToString().Length);
}
using (var dc = new DataClasses1DataContext())
{ // 2: LoadWith
dc.Log = new StringWriter();
var opt = new DataLoadOptions();
opt.LoadWith<Person>(p => p.PersonPhones);
dc.LoadOptions = opt;
RoundtripAndCount("LoadWith", dc.Persons);
Console.WriteLine("Log: " + dc.Log.ToString().Length);
}
using (var dc = new DataClasses1DataContext())
{ // 3: iterate manually
dc.Log = new StringWriter();
// manually iterate the data (LINQ-to-Objects)
GC.KeepAlive(dc.Persons.AsEnumerable().Sum(p=>p.PersonPhones.Count())); // just an opaque method
RoundtripAndCount("Enumerated", dc.Persons);
Console.WriteLine("Log: " + dc.Log.ToString().Length);
}
}
static void RoundtripAndCount(string caption, IEnumerable<Person> people)
{
Console.WriteLine();
Console.WriteLine(caption);
Console.WriteLine(new string('=', caption.Length));
List<Person> list = people.ToList(), clone;
using(var ms = new MemoryStream())
{
var ser = new DataContractSerializer(typeof (List<Person>));
ser.WriteObject(ms, list);
ms.Position = 0;
clone = (List<Person>) ser.ReadObject(ms);
Console.WriteLine("Bytes: " + ms.Length);
}
Func<Person, int> phoneCount = p => p.PersonPhones.HasLoadedOrAssignedValues ? p.PersonPhones.Count() : 0;
Console.WriteLine("Original person count: " + people.Count());
Console.WriteLine("Original phone count: " + people.Sum(phoneCount));
Console.WriteLine("Deser person count: " + clone.Count());
Console.WriteLine("Deser phone count: " + clone.Sum(phoneCount));
}
}
作为旁注,我可以调整protobuf-net以说服L2S为其提供数据(DataContractSerializer
决定忽略它),但这会重现方案3巨大的N + 1成本。因此,我不打算继续追求......