我需要一些帮助!我正在尝试使用Entity Framework,WCF,MVVM和WPF技术创建我的第一个应用程序。我对他们都很陌生。所以我使用Entity Framework为我的数据库创建了一个模型。然后我创建我的WCF服务类。我已经阅读了近50篇关于EF和WCF服务的文章,我现在都在混淆。我知道我不应该直接暴露我的模型。目前我使用此代码作为服务合同:
namespace Ohmio.DataService
{
[ServiceContract]
public class OhmioService
{
[OperationContract]
public IEnumerable<vw_Pedidos> ListarPedidos(string IDComprobante, bool bEntregados, int Numero = -1, int IDCliente = -1)
{
using (var context = new OhmioTestNet())
{
string sqlString="SELECT VALUE cs FROM OhmioTestNet.vw_Pedidos AS cs WHERE cs.ID_Comprobante=='" + IDComprobante + "' AND ";
if (Numero != -1) sqlString += "cs.Numero=="+ Numero.ToString() +" AND ";
if (IDCliente != -1) sqlString += "cs.ID_Cliente=="+ IDCliente.ToString()+" AND ";
if (!bEntregados) sqlString += "cs.Entregado==false AND ";
sqlString =sqlString.Substring(0,sqlString.Length-4);
ObjectQuery<vw_Pedidos> Pedidos = context.CreateQuery<vw_Pedidos>(sqlString);
var result = Pedidos.ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
[OperationContract]
public IEnumerable<Clientes> GetClientes()
{
using (var context = new OhmioTestNet())
{
var result = context.Clientes.Where(f => f.Activo == true).ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
}
}
我的问题:
问题在于,不要直接公开我的数据模型,对吧?所以我在这里返回类vw_Pedidos
的分离实体。这是一种不好的做法吗?
我已经阅读了很多关于DTO和POCO的对象,我应该使用哪个代替上面的代码?
如果我使用DTO或POCO通过WCF进行传输,是否必须为每个数据库对象手动创建DTO?我是否必须手动为每个数据库对象创建所有属性(字段)?
如果我向数据库对象添加一个新字段并需要在客户端上显示它,我是否必须更新我的EF模型,手动将新字段添加到DTO或POCO对象?这听起来像是一场维护噩梦!
使用EntitiesToDTOs是基于EF对象自动创建DTO的好选择吗?
我可以使用DTO将数据更新回数据库吗?
很抱歉有多个问题。请帮帮我吧!我正在寻找一种模式,让我能够轻松维护,关注分开的代码。谢谢!
更新
根据TomTom的建议,我读了很多关于POCO,EF和Linq to Entities的内容。之后我重写了我的整个应用程序。我将我的代码划分为5个项目:
1)数据层
2)ModelLayer
3)BusinessLyer
4)WCF服务层
5)WPF客户端
对于第1层到第5层的通信,我使用POCO T4模板映射到实体框架的POCO类。要通过WCF通信第4层和第5层,我想使用自定义类来隐藏客户端的某些字段(我不想公开整个POCO类)所以我使用linq重写了过滤函数到实体和投影到IEnumerable的:
public IEnumerable<PedidosList> Pedidos_Listar(string sComprobante, Clientes MyCliente = null, DateTime? dDesde = null, DateTime? dHasta = null, bool bCumplidos = false)
{
using (var context = new OhmioEntities())
{
IEnumerable<PedidosList> query =
from Pedidos in context.Pedidos
join Clientes in context.Clientes on Pedidos.ID_Cliente equals Clientes.ID_Cliente
where Pedidos.ID_Comprobante == sComprobante
select new PedidosList {ID_Pedido = Pedidos.ID_Pedido, Fecha=Pedidos.Fecha, Aprobado=Pedidos.Aprobado, Bruto=Pedidos.Bruto, Cliente=Clientes.RazonFantasia,
FechaEntrega=Pedidos.FechaEntrega, Neto=Pedidos.Neto, Numero=Pedidos.Numero, Observaciones=Pedidos.Observaciones, Entregado=Pedidos.Entregado, ID_Cliente=Pedidos.ID_Cliente };
if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
if (MyCliente != null) query = query.Where(i => i.ID_Cliente == MyCliente.ID_Cliente);
if (dDesde != null && dHasta != null) query = query.Where(i => i.Fecha >= dDesde && i.Fecha <= dHasta);
if (bCumplidos == false) query = query.Where(i => i.Entregado == false);
return query.ToList();
}
}
这是最好的方法吗?我可以在滤镜后进行投影吗?谢谢!
答案 0 :(得分:15)
问题在于,不要直接公开我的数据模型,对吧?所以在这里 我正在返回类vw_Pedidos的脱离实体。这是一种不好的做法吗?
是
我已经阅读了很多关于DTO和POCO的对象,我应该使用什么而不是上面的 码?
两者。鉴于DTO通常是POCO。也许你试着理解MEAN这几个字。 POCO是一个普通的旧C#对象&#34; (不需要从基类继承),这对于POCO来说是完全正常的。
如果我使用DTO或POCO通过WCF进行转移,我是否必须为每个人创建一个DTO 数据库对象?我是否手动为每个数据库对象创建了所有属性(字段)?
没有。有没有听说过T4?这可以编写脚本。也就是说,这些通常不是数据库而是API对象--WCF服务是服务器程序的(公共)前端。
如果我向DB对象添加一个新字段并需要在客户端上显示它,我是否必须更新我的 EF模型,将新字段手动添加到DTO或POCO对象中?这听起来 像维持生命一样!
绝对是一个。如果你不假思索地做事。说真的,一旦你敲定了基本模型,这不是每15分钟发生一次的事情。它还包括前端和逻辑方面的重要工作 - 我的意思是,如果属性没用,那么嘿,为什么要把它放进去?如果它没用,那么无论如何都要做很多工作。并且模型可以更新,不需要重新生成。
哎呀,我通常使用非平凡的数据库。在这种情况下,更改不是&#34;重新生成模型&#34;,它还包括&#34;编写用于版本控制的#sql更新脚本&#34;和&#34;测试更新性能&#34; (将字段添加到具有默认值的数十亿行表并生成索引可能需要一些时间)。它仍然不是噩梦,因为这不会每5分钟发生一次。最重要的东西不是&#34;添加字段&#34;,它是&#34;程序&#34;。
我可以使用DTO将数据更新回数据库吗?
还有什么?
请帮帮我吧!我正在寻找一种让我容易保持的模式, 关注分开的代码
你找不到一个。这是做出正确妥协的问题。您似乎过高估计了项目中发生的变化量。
您可以更好地假设WCF服务是信任边界和公共API - 非常类似于网站,仅供计算机使用。您在那里公开的对象必须绝对不符合数据库内部。最好单独生成它们并可能将它们更改为更符合公共API所需的内容 - 而不是将后端实现细节公开给API。
我不得不说,你的工作因为访问数据库的古老和绝对反对的方式而变得更加复杂 - 开始使用适当的sql生成器和对象映射器,或者你将拥有一个维护噩梦就在那里,不管你怎么做其余的事。将这样的SQL字符串放在一起是一个严重的“不”,“永远不会”#34;并查看如何通过WCF公开OData。这为您提供了通过URL查询功能。