POCO有100多个字段(使用DataMember(Order = X)属性为ProtoBuf.Net序列化标记它们)。
我们需要对文件进行一些后期处理,其中一个字段的值需要调用(我们只能在读过一次后才能执行)更新并再次保存。我们正在重新启动新文件,这显然有一些IO /文件开销。
我有什么方法可以更新现有文件,其中只需要更新和保存Field" X"的值。希望这比从头开始生成新文件更快。
示例POCO数据结构(并且每个文件将包含~3mln这些项目)
[DataContract]
public class DataItem
{
[DataMember(Order=1)]
public string ProfitCentre {get; set;}
[DataMember(Order=2)]
public string BusinessFunction {get; set;}
//this is the value that needs to be updated once file is written
[DataMember(Order=3)]
public double AdjustedAmount {get; set; }
}
答案 0 :(得分:1)
这取决于模型的结构。 protobuf格式允许append-as-update,这意味着:可以在文件的 end 处写入一个值,然后将其应用于代码模型。但是,有一个限制:它不适用于repeated
元素(包括map<...>
元素)。它可以应用于根对象或任意数量的optional
/ required
子对象,但不能应用于repeated
。另一个限制是您需要一个写入该值且仅 该值的API。有多种方法可以实现这一目标,例如,如果我们有:
Foo
- Bar (field 3 of Foo)
- Blap (field 7 of Bar)
- X (string, field 4 of Blap)
然后 这样做的其中一种方式就是为了这个目的而拥有第二个模型 来更新X
字段,如下:
[ProtoContract]
class FooUpdate {
[ProtoMember(3)]
public BarUpdate Bar {get;set;} = new BarUpdate();
}
[ProtoContract]
class BarUpdate {
[ProtoMember(7)]
public BlapUpdate Blap {get;set;} = new BlapUpdate();
}
[ProtoContract]
class BlapUpdate {
[ProtoMember(4)]
public string X {get;set;}
}
现在;假设我们之前在文件中写了常规 Foo
,我们可以构造:
var obj = new FooUpdate { Bar = { Blap = { X = "abcdef" } } };
Serializer.Serialize(existingFile, obj);
仅附加此数据(我假设此处existingFile
位于末尾,用于附加目的)。
请注意,使用&#34;条件序列化&#34;也可以实现类似的功能,但是当我们可以......没有任何东西时,将一切关闭似乎需要付出很多努力关掉。
但是,如果您要编写的数据位于repeated
/ map<...>
字段中,则您只需重写整个文件即可。在该上下文中,append将导致其他列表元素,或者来自地图元素的 loss 数据。