【问题标题】:How to trim values using Linq to Sql?如何使用 Linq to Sql 修剪值?
【发布时间】:2009-03-16 20:13:18
【问题描述】:

在数据库中,我有一个名为 Contact 的表。名字和其他此类字符串字段旨在使用 Char 数据类型(不是我的数据库设计)。我的对象 Contact 映射到属性中的字符串类型。如果我想做一个通过 id 检索联系人对象的简单测试,我会这样做:

Contact contact = db.Contacts.Single(c => c.Id == myId);
Contact test = new Contact();
test.FirstName = "Martin";

Assert.AreEqual(test.FirstName, contact.FirstName);

contact.FirstName 的值是“Martin”,因为它是 char 类型。加载 FirstName 属性时在哪里可以截获它? OnFirstNameChanging(string value) 不会在初始加载(接触)时调用,但会在测试对象上调用。

【问题讨论】:

标签: c# linq-to-sql


【解决方案1】:

也许你可以把它放在 OnLoaded() 部分方法中?注意:我从未使用过它,但我认为它看起来像这样:

public partial class Contact
{
    partial void OnLoaded()
    {
        FirstName = FirstName.Trim();
    }
}

【讨论】:

  • 这行得通。每个字段都相当容易,因为我没有显示那么多字段。谢谢。
  • 这将生成一个属性更改事件——这可能会触发其他操作——并且可能会导致对数据库进行不必要的更新,因为您正在更改属性的值而不进行任何语义更改内容。
  • 问题的重点是找到做这种逻辑的地方(在本例中为 OnLoaded());该方法本身可以很容易地由“_FirstName = _FirstName.Trim();”组成以避免触发属性更改事件。
  • 这可能是我需要的一个好主意,因为我无法更改数据库架构。我真的只使用这个类作为数据对象来保存数据库记录的值。如果我能截获一个属性加载事件就好了,但我不能。
  • 请注意,只有在此类对应的表具有主键时,才能使用 OnLoad() 方法。
【解决方案2】:

如果您无法更改架构,您可能希望将设计器生成的访问器设为私有/受保护,并创建一个公共访问器以在部分类实现中作为属性的前端。然后,您可以修剪 get 访问器中的值。

public partial class Contact
{

    public string RealFirstName
    {
       get { return this.FirstName.Trim(); }
       set { this.FirstName = value; }
    }

    ...
}

【讨论】:

  • 这是一个很好的解决方案,因为字段不仅是 char 类型,而且还被称为 First_Name。所以我也可以修复所有字段,而无需在我的对象设计器中更改它。
  • 问题是当我创建一个查询并尝试使用 FullName = c.FirstName + ' ' + c.LastName 之类的东西时。我收到了无法翻译表达式,无法将其视为本地表达式消息。
  • 完成过滤后,您可以使用 ToList() 生成实际查询,然后在结果列表中进行选择。由于此时它们是对象,因此 FullName 的构造应该可以工作。
  • 我使用的是轻量级对象,而不是返回列表。这是爆炸的那一行:ContactName = act.PhoneContact.FirstName + " " + act.PhoneContact.LastName
【解决方案3】:
Contact contact = db.Contacts.Single(c => c.Id.Trim() == myId);

并检查 LINQ 提供程序是否将其转换为适当的 SQL。

【讨论】:

  • 我认为问题不在于 Id 字段。
  • @tvanfosson - 我认为操作只是为了举例,而不是从字面上理解。
  • @threadster 您已链接到使用 LINQ to Entities 的 Entity Framework 使用的 Entity SQL。旧的 pre-EF ORM 使用 LINQ to SQL。
【解决方案4】:

这取决于您对架构和代码的控制。

如果值是通过调用带有所有参数的构造函数来设置的,则在将它们分配给成员变量时进行修剪等。

如果它们被分配给属性(可能来自示例),请更改 SET 访问器,以便它在那里进行修剪。

如果您在某个时候确实想要前导或尾随空格,则确实存在潜在问题。

如果您无法修改基类代码,请尝试使用部分类,或从该类继承并覆盖那里的属性。

如果你不能这样做,那么我的最后一个建议是编写一个工厂类,你将创建的对象传递给它,它会按照你想要的规则清理它。

【讨论】:

    【解决方案5】:

    在尝试搜索 Martin 之前,您可以在联系人列表中运行 ForEach

    var contacts = db.Contacts.ForEach(c => c.FirstName = c.FirstName.Trim());
    Contact contact = contacts.Single(c => c.Id == myId);
    contact.FirstName // = "Martin"
    

    但是这种方式如果要针对多个字段进行的话,维护起来就不太方便了。

    【讨论】:

    • 如果他有 100,000 个联系人会怎样?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多