WCF DataMember 序列化问题

发布于 2024-08-10 17:38:23 字数 596 浏览 7 评论 0原文

好的,我已经完成了创建 DTO 以通过网络发送模型的漫长过程,但我不觉得自己走在正确的道路上。

我的问题是,我的模型中的大多数实体无论如何都与 DTO 相差无几。我基本上有一个贫乏的域模型,这很好,但它也让我想知道是否需要为这些实体建模 DTO。

所以我的第一个问题是,如果只是序列化我的实体并通过网络传递它们,我可能会遇到什么问题?

其次,给出一个更具体的问题,如下所示的属性签名:

public virtual Unit Unit { get; set; }

我是否可以仅通过线路发送 UnitId 而不是序列化的单元对象?

编辑: 抱歉,我的问题不够清楚,正如你们所发布的,我知道我只能指定单位的 Id 属性,但这对我不起作用。

原因是这个属性(上面) )位于“Country”类上,我希望仅在调用“CountryService.GetCountry(Id)”或类似时返回 UnitID。但是在流动的服务调用“UnitService.GetUnit(Id)”上,我希望序列化更多属性并通过网络发送。 希望这是有道理的。

谢谢,克里斯。

Ok, so I was part way through the long winded process of creating DTOs for sending my model over the wire and I don't feel like I'm going down the right route.

My issue is that most of the entities in my model are not much more that DTOs anyway. I basically have an anaemic domain model, which is fine but it also make me wonder if I need to model DTOs for these entities.

So my first question is what issues might I hit if just serialize my entities and pass these about over the wire?

Secondly, a more specific question is given a property signature like so:

public virtual Unit Unit { get; set; }

Is it possible for me just to send over the wire the UnitId and not the serialized unit object?

Edit:
Sorry I wasn't clear enough with my question, as you guys have posted I know that I can specify only the Id property of unit but this wont work for me.

The reason is that this property (above) is on a "Country" class and I want the UnitID only returning when I call "CountryService.GetCountry(Id)" or simmilar. BUT on the floowing service call "UnitService.GetUnit(Id)" I want more properties to be serialized and sent over the wire.
Hope this makes sense.

Thanks, Chris.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可可 2024-08-17 17:38:23

<块引用>

其次,给出一个更具体的问题,如下所示的属性签名:

公共虚拟单元单元 { get;放; }

我可以通过网络发送 UnitId 和
不是序列化的单元对象?

当然 - 确保

  1. 不要使用 [DataMember] 标记您的 Unit 属性,
  2. 创建您执行的第二个名为 UnitId 的属性 strong> 标记为数据成员,
  3. 确保您的客户端始终能够以某种方式仅从 UnitId 重建 Unit

更新:

原因是这个属性
(上图)正在上“乡村”课,我
希望 UnitID 仅在我返回时返回
调用“CountryService.GetCountry(Id)”
或类似。但在流动
服务调用“UnitService.GetUnit(Id)”
我想要更多的房产
序列化并通过网络发送。
希望这是有道理的。

在这种情况下,您需要两个单独的 DataContracts - 一个用于仅包含 UnitIdCountryService.GetCountry(Id) 调用,另一个用于 UnitService .GetUnit(Id) 调用,其中包含您想要的 Unit 的所有属性。

您不能有条件地发送某些属性(或不发送),具体取决于运行时的决定。 DataContracts 在 XML 模式中建模,并且是相当静态的。如果您有两组所需的属性,则需要两个单独的 DataContracts。

Secondly, a more specific question is given a property signature like so:

public virtual Unit Unit { get; set; }

Is it possible for me just to send over the wire the UnitId and
not the serialized unit object?

Sure - make sure to

  1. not mark your Unit property with a [DataMember]
  2. create a second property called UnitId which you do mark as data member
  3. make sure your clients can always somehow reconstruct the Unit class from only it's UnitId

UPDATE:

The reason is that this property
(above) is on a "Country" class and I
want the UnitID only returning when I
call "CountryService.GetCountry(Id)"
or simmilar. BUT on the floowing
service call "UnitService.GetUnit(Id)"
I want more properties to be
serialized and sent over the wire.
Hope this makes sense.

In that case, you need two separate DataContracts - one for the CountryService.GetCountry(Id) call with just the UnitId in it, and another one for the UnitService.GetUnit(Id) call with all the properties of Unit that you want in it.

You cannot conditionally send some properties - or not - depending on a runtime decision. DataContracts are modelled in XML schema, and that is pretty static. If you have two sets of properties that you need, you need two separate DataContracts.

小忆控 2024-08-17 17:38:23

您可以通过添加 NonSerializedAttribute (msdn)。您仍然会获得 Unit,但只能使用 UnitId。

我认为仅序列化 DTO 不会有问题。
您是否使用了 DTO 中的所有信息?
您是否跨越域边界?我会在每个域中创建新实体并为它们制作映射器。

You can downsize the object that will be passed over the wire by adding the NonSerializedAttribute (msdn). You will still get Unit, but only with the UnitId.

I don't think there would be a problem in just serializing your DTO's.
Do you use all of the information in your DTO's?
Are you crossing domain boundaries? I would create new entities in every domain and make mappers for them.

樱花细雨 2024-08-17 17:38:23

据我所知,您的问题源于这样一个事实:您有一个由 DTO 制成的本地显式声明的对象图。我的意思是你已经声明了 public Unit Unit { get;放; } 在您的 Country 模型上(不知道为什么您将它们声明为 virtual 但这与当前的问题没有直接关系),而不是尝试一种方法保证对象图在单个对象图节点的退化情况下的简单性。

例如,考虑以 public UnitID Unit { get; 的形式定义模型上的每个“引用”属性。放; } 其中 UnitID 实际上可能是 intGuid 或任何您用来唯一标识和区分 Unit 的内容> 彼此的模型。只要您有对另一个模型的引用或一组引用,请将其替换为其标识符类型而不是其实际类型。该策略非常适合一组持久化的模型,例如从/到带有每个模型的身份密钥的数据库。这样做可以使序列化变得简单,而不必担心循环引用,因为它们现在是不可能的。从技术上讲,不再有引用(即直接引用;现在是间接引用)。我们现在只是在域模型设计中添加一个间接层。现在让我们适应这一间接层。

既然您声称您对贫血域模型方法很满意,那么这应该很适合。您在模型设计中支付了较小的(恕我直言)间接成本,并将其换取基于接口的数据检索方法的主要(恕我直言)好处:

public interface IUnitRepository {
    Unit GetUnit(UnitID id);
    IEnumerable<Unit> GetUnits(IEnumerable<UnitID> ids);
    // etc.
}

在您的消费者代码中(即使用此接口的代码和您的< code>Unit 域模型),通过执​​行接口调用来获取间接引用指向的底层模型来遍历隐含对象图,看起来只是稍微复杂一些。

BEFORE:

Country ct = ...;    // I assume you have this reference already
Unit ut = ct.Unit;

AFTER:

// Somewhere earlier in your code, i.e. not *every* time this type of code appears
IUnitsRepository repo = new SomeUnitsRepositoryImpl();
Country ct = ...;    // I assume you have this reference already
Unit ut = repo.GetUnit(ct.UnitID);

如果这在语法上困扰您,您可以定义一组在 Country 上键入的扩展方法,格式为:

public static Unit Unit(this Country c, IUnitsRepository repo) {
    return repo.GetUnit(c.UnitID);
}

AFTER EXTENSION METHODS:

IUnitsRepository repo = new SomeUnitsRepositoryImpl();
Country ct = ...;    // I assume you have this reference already
Unit ut = ct.Unit(repo);

基于接口的方法为您带来了一系列经典的好处,例如关注点分离、可测试性、消费者与生产者隔离等等。此外,您现在可以通过接口的实现类型更直接地控制对象生命周期。我的意思是,您不必假设 Unit GetUnit(UnitID id) 方法的实现是天真的。此方法现在可以利用与 SomeUnitsRepositoryImpl 实例绑定的 Dictionary 执行一些本地内存缓存。

有点啰嗦,但希望对你有帮助。从所提供的详细信息来看,似乎并不明显,我目前正在我的工作地点尝试这种设计,以处理我们的记录数据库系统。 :) 我真的很喜欢它所提供的所有灵活性,而只需在域模型的设计中添加一级间接性即可。

From what I can understand, your problem stems from the fact that you have a local explicitly declared object graph made from your DTOs. What I mean is that you have declared public Unit Unit { get; set; } on your Country model (not sure why you're declaring them virtual but that's not directly related to the issue at hand) rather than trying an approach that guarantees simplicity of the object graph into the degenerate case of a single object graph node.

For example, consider defining every "reference" property on your model in the form public UnitID Unit { get; set; } where UnitID might actually be int or Guid or whatever you use to uniquely identify and distinguish Unit models from each other. Wherever you have a reference or set of references to another model, replace it with its identifier type instead of its actual type. This strategy lends itself well to a persisted set of models e.g. from/to a database with identity keys for each model. Doing this gets you simplicity of serialization without having to worry about circular references because they are now impossible. Technically, there are no more references (i.e. direct references; they are now indirect references). We're now just adding a layer of indirection in your domain model design. Now let's accommodate for that layer of indirection.

Since you've claimed that you're fine with the anemic domain model approach then this should fit well with that. You pay the minor (IMHO) cost of indirection in your model design and trade it up for the major (IMHO) benefits of an interface-based approach to data retrieval:

public interface IUnitRepository {
    Unit GetUnit(UnitID id);
    IEnumerable<Unit> GetUnits(IEnumerable<UnitID> ids);
    // etc.
}

In your consumer code (i.e. the code that consumes this interface and your Unit domain models), it only looks slightly more complex to traverse the implied object graph by performing interface calls to get the underlying models pointed to by the indirect references.

BEFORE:

Country ct = ...;    // I assume you have this reference already
Unit ut = ct.Unit;

AFTER:

// Somewhere earlier in your code, i.e. not *every* time this type of code appears
IUnitsRepository repo = new SomeUnitsRepositoryImpl();
Country ct = ...;    // I assume you have this reference already
Unit ut = repo.GetUnit(ct.UnitID);

If this bothers you syntactically, you can define a set of extension methods typed on Country of the form:

public static Unit Unit(this Country c, IUnitsRepository repo) {
    return repo.GetUnit(c.UnitID);
}

AFTER EXTENSION METHODS:

IUnitsRepository repo = new SomeUnitsRepositoryImpl();
Country ct = ...;    // I assume you have this reference already
Unit ut = ct.Unit(repo);

The interface-based approach gets you the classical set of benefits such as separation of concerns, testability, consumer-producer insulation, and many more. Furthermore, you now get more direct control over object lifetime via the implementation type of your interface. What I mean is that you shouldn't have to assume naivety of implementation of your Unit GetUnit(UnitID id) method. This method could now perform some local in-memory caching utilizing a Dictionary<UnitID, Unit> tied with the instance of SomeUnitsRepositoryImpl.

A bit long-winded, but I hope it helps. As if it weren't obvious from the amount of detail provided, I am currently toying with this design at my place of employment for dealing with our system of record database. :) I am really loving all the flexibility it gives me all at the simple cost of adding one level of indirection in the design of the domain models.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文