Web方法WCF中的返回请求

时间:2015-12-31 12:51:59

标签: c# entity-framework wcf

我有Web服务和一个方法,它通过Entity Framework向我的表'Customer'发出请求。

我想返回我的请求结果:

[WebMethod]
public Customer MyMethod(int id)
{
    Model model = new Model();
    Customer customer = new Customer();

    try
    {
        customer = model.Customer.Where(x => x.Name == id).First();
    }
    catch (Exception ex)
    {
        throw new System.NullReferenceException(ex.Message, ex.InnerException);
    }

    return customer;
}

我的班级客户(由EF生成):

[Table("Customer")]
public partial class Customer
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    public int? Adress_id { get; set; }

    public virtual Adress Adress { get; set; }
}

班级地址(由EF生成):

[Table("Adress")]
public partial class Adress
{
    public Adress()
    {
        Customer = new HashSet<Customer>();
    }

    public int Id { get; set; }

    [Column("Adress")]
    [StringLength(255)]
    public string Adress1 { get; set; }

    [StringLength(50)]
    public string Town { get; set; }

    public virtual ICollection<Customer> Customer{ get; set; }
}

但是当我用SoapUI调用我的方法时,我没有答案。如果我删除虚拟Adress属性,那么我有一个答案,但我还需要取回地址(联合)

谢谢

3 个答案:

答案 0 :(得分:0)

由于virtual属性,无法将模型序列化以发送它们。您在客户中的地址引用了客户,这再次引用了地址......这是一个无限循环。因此,您可以使用DTO(数据传输对象)类来传输数据。对于您的Customer模型,它看起来像这样:

public class CustomerDTO
{
  public int Id { get; set; }
  public string Name { get; set; }
  public int? Adress_id { get; set; }

  public Adress Adress { get; set; }      
}

在通过WCF发送之前,您必须将Customer转换为CustomerDTO个对象。您甚至可以使用linq在一个语句中执行此操作:

var obectToTransfer = db.Customers.Where(c => c.Id == 5)
                                  .Select(c => new CustomerDTO
                                  {
                                     Id = c.Id
                                     ...
                                  }).FirstOrDefault();

答案 1 :(得分:0)

如果要在查询中明确加载相对属性,可以通过使用Include扩展方法的Eagerly Loading来实现:

 customer = model.Customer.Include(c=>c.Address).Where(x => x.Name == id).First();

您也可以使用Explicit Loading:

 customer = model.Customer.Where(x => x.Name == id).First();
 context.Entry(customer).Reference(p => p.Address).Load();

现在我建议您检查数据库中的关系。如果您没有使用Fluent Api来配置该关系,那么EF不知道Address_id是该关系的FK。如果外键属性名为[Target Type Key Name][Target Type Name] + [Target Type Key Name],[Navigation Property Name] + [Target Type Key Name],则会按惯例发现它。覆盖此约定的一种方法是使用ForeignKey属性。因此,首先检查数据库中的关系,然后检查是否有Address与您要加载的Customer相关联。您应该能够使用我上面建议的两种变体之一加载Address导航属性。

答案 2 :(得分:0)

我在班级客户中删除了关键字虚拟:

[Table("Customer")]
public partial class Customer
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    public int? Adress_id { get; set; }

    public Adress Adress { get; set; }
}

我删除了我的类Adress中的构造函数和属性ICollection<Customer> Customer

[Table("Adress")]
public partial class Adress
{
    public int Id { get; set; }

    [Column("Adress")]
    [StringLength(255)]
    public string Adress1 { get; set; }

    [StringLength(50)]
    public string Town { get; set; }
}

我的查询:customer = model.Customer.Include("Adress").Where(x => x.Id == 2).First();

有效!

我的回答:

<a:Adress>
   <a:Adress1>101 Madison Ave</a:Adress1>
   <a:Id>1</a:Id>
   <a:Town>New York</a:Town>
</a:Adress>
<a:AdressId>1</a:AdressId>
<a:Name>John</a:Name>
<a:Id>2</a:Id>

但它不实用