使用代理将可跟踪的 EF 实体传递给 WCF 服务
Passing trackable EF Entity to WCF service, using proxies
我目前正在毫无问题地将我的实体从 WCF 发送到客户端。问题是,当我将一个给定实体发送回 WCF(自其在客户端创建以来的相同引用)时,代码 Context.Entry(entity).State
returns Detached
.
如果我对 Context.ChangeTracker.Entries()
进行检查,我发现我的跟踪实体在那里,但它们似乎与我从客户那里收到的实体不同 "reference related"。
有什么建议吗?我想在 WCF -> Client -> WCF
.
中一直使用相同的参考
长话短说,您将无法避免断开连接。 EF 正在创建一个不属于您 DataContract
的代理 class,因此补充跟踪数据在 [un] 序列化过程中丢失。
不过,好消息是使用如下方式重新附加实体非常容易:
[OperationContract]
void Update(Entity entity)
{
db.Set<Entity>().Attach(entity)
// carry on
}
但是,我会考虑使用数据传输对象 (DTO) 并停止通过网络发送您的实际实体。您的数据可能很简单,但从长远来看 运行 它将节省您在版本控制、安全性等方面的时间。还有像 AutoMapper 这样的库可以使转换变得非常简单。例如
// Example EF model
[Table("Users")]
class UserEntity
{
[Key]
public Guid Id { get; set; }
[Required]
public String UserName { get; set; }
[Required]
public String Password { get; set; }
}
// Example DTO model
[DataContract]
class UserDto
{
[DataMember]
public Guid Id { get; set; }
[DataMember]
public String UserName { get; set; }
// No need to send Password over the wire.
// Let's keep things a bit more secure.
}
然后绑定:
Mapper.CreateMap<UserEntity,UserDto>()
.ForMember(d => d.Id, m => m.MapFrom(s => s.Id))
.ForMember(d => d.UserName, m => m.MapFrom(s => s.UserName))
.ForSourceMember(s => d.Password, m => m.Ignore())
.ReverseMap()
.ForMember(d => d.Id, m => m.MapFrom(s => s.Id))
.ForMember(d => d.UserName, m => m.MapFrom(s => s.UserName))
.ForMember(d => d.Password, m => m.Ignore());
// Confirm we have everything configured correctly.
Mapper.AssertConfigurationIsValid();
然后,在实践中:
UserDto userDto = /* incoming model */
UserEntity user = Mapper.Map<UserEntity>(userDto);
db.Set<UserEntity>().Attach(user);
// carry on
我目前正在毫无问题地将我的实体从 WCF 发送到客户端。问题是,当我将一个给定实体发送回 WCF(自其在客户端创建以来的相同引用)时,代码 Context.Entry(entity).State
returns Detached
.
如果我对 Context.ChangeTracker.Entries()
进行检查,我发现我的跟踪实体在那里,但它们似乎与我从客户那里收到的实体不同 "reference related"。
有什么建议吗?我想在 WCF -> Client -> WCF
.
长话短说,您将无法避免断开连接。 EF 正在创建一个不属于您 DataContract
的代理 class,因此补充跟踪数据在 [un] 序列化过程中丢失。
不过,好消息是使用如下方式重新附加实体非常容易:
[OperationContract]
void Update(Entity entity)
{
db.Set<Entity>().Attach(entity)
// carry on
}
但是,我会考虑使用数据传输对象 (DTO) 并停止通过网络发送您的实际实体。您的数据可能很简单,但从长远来看 运行 它将节省您在版本控制、安全性等方面的时间。还有像 AutoMapper 这样的库可以使转换变得非常简单。例如
// Example EF model
[Table("Users")]
class UserEntity
{
[Key]
public Guid Id { get; set; }
[Required]
public String UserName { get; set; }
[Required]
public String Password { get; set; }
}
// Example DTO model
[DataContract]
class UserDto
{
[DataMember]
public Guid Id { get; set; }
[DataMember]
public String UserName { get; set; }
// No need to send Password over the wire.
// Let's keep things a bit more secure.
}
然后绑定:
Mapper.CreateMap<UserEntity,UserDto>()
.ForMember(d => d.Id, m => m.MapFrom(s => s.Id))
.ForMember(d => d.UserName, m => m.MapFrom(s => s.UserName))
.ForSourceMember(s => d.Password, m => m.Ignore())
.ReverseMap()
.ForMember(d => d.Id, m => m.MapFrom(s => s.Id))
.ForMember(d => d.UserName, m => m.MapFrom(s => s.UserName))
.ForMember(d => d.Password, m => m.Ignore());
// Confirm we have everything configured correctly.
Mapper.AssertConfigurationIsValid();
然后,在实践中:
UserDto userDto = /* incoming model */
UserEntity user = Mapper.Map<UserEntity>(userDto);
db.Set<UserEntity>().Attach(user);
// carry on