将POCO映射到Linq到Sql的字符串,以便我可以在我的POCO上使用Linq

时间:2009-08-14 10:56:28

标签: c# linq linq-to-sql

我正在访问一个数据库列,其中电话号码存储为varchar,格式为+ a-b:c,其中a =国家/地区代码,b =电话号码,c =扩展名。例如。 + 44-07700123456:123

所以我有一个处理序列化的类型:

public struct PhoneNumber {
  public PhoneNumber(string val) {  /*...*/ }
  public override string ToString() { /*...*/ }
  public static PhoneNumber TryParse(string val) { /*...*/ }
}

和POCO:

public class Customer {
  public PhoneNumber? HomePhone;
}

然后在我的数据访问代码中使用了一些Linq:

public IQueryable<Customers> GetCustomers() {
  var customers = (from c in DataContext.Customers
  select new Customer {
    HomePhone = PhoneNumber.TryParse(c.HomePhone)
  });
  return customers;
}

到目前为止一切顺利,从数据库中检索记录时一切正常,但我的问题是我无法对结果执行Linq查询,如:

GetCustomers().Where(c => c != null && c.HomePhone.Value.ToString().Contains("123"));

我收到错误“Method'System.Nullable`1 [PhoneNumber] TryParse(System.String)'没有支持的SQL转换”。现在我知道我可以在GetCustomers()中执行电话号码搜索,但这并不理想。

有没有办法让Linq知道如何将我的linq翻译成sql?所以我可以做一些像GetCustomers()。其中​​(c =&gt; c.HomePhone.Value.ToString()。包含(“123”))?

P.S。不确定这个标题,欢迎任何替代方案。

2 个答案:

答案 0 :(得分:0)

问题是你的PhoneNumber.TryParse()调用被转换成一个发送到服务器的表达式,它不理解。此外,没有办法告诉SQL您的结构,因此您将无法根据解析的值执行服务器端查询。一种选择是捕获字符串值并将PhoneNumber.TryParse()位移到其他位置。例如:

public class Customer {
  public string HomePhoneString;

  private bool _HomePhoneParsed;
  private PhoneNumber? _HomePhone;
  public PhoneNumber? HomePhone
  {
    get
    {
      if(!_HomePhoneParsed)
      {
        _HomePhone = PhoneNumber.TryParse(HomePhoneString);
        _HomePhoneParsed = true;
      }
      return _HomePhone;
    }
  }
}

public IQueryable<Customers> GetCustomers() {
  var customers = (from c in DataContext.Customers
  select new Customer {
    HomePhoneString = c.HomePhone
  });
  return customers;
}

然后你可以查询服务器端:

GetCustomers().Where(c => c.HomePhoneString != null && c.HomePhoneString.Contains("123"))

或客户端:

GetCustomers().AsEnumerable()
              .Where(c => c.HomePhone != null && c.HomePhone.Value.Contains("123"))

答案 1 :(得分:0)

对此进行跟进,另一种解决方案是将PhoneNumber更改为类并添加“Value”属性以序列化/反序列化,如:

public class PhoneNumber {

  public override string ToString() { /*...*/ }
  public Parse(string val) { /*...*/ }

  public string Value {
    get {
      return ToString();
    }
    set {
      Parse(value);
    }
  }
}

这种代码并不适合属性,但它允许您在Linq查询中初始化HomePhone对象,如:

var customers = (from c in DataContext.Customers
  select new Customer {
    FirstName = c.FirstName,
    HomePhone = new PhoneNumber {
      Value = c.HomePhone
    }
  });

这意味着您可以使用序列化程序,如:

customers.Where(x => x.HomePhone.Value.Contains("123"));
相关问题