如何使用Linq to Sql修剪值?

8

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

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”。当加载FirstName属性时,我应该在哪里拦截它?在初始加载(联系人)时不会调用OnFirstNameChanging(string value),但在测试对象上会调用。


你可以使用contact.FirstName.Trim()来完成这个操作。我看到了自己的一些旧代码,现在需要更新。以下是关于规范字符串LINQ to SQL函数的参考链接:https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/string-canonical-functions。 - threadster
5个回答

8
也许你可以把它放在OnLoaded()部分方法中?注意:我从未使用过这个,但我认为它应该像这样:
public partial class Contact
{
    partial void OnLoaded()
    {
        FirstName = FirstName.Trim();
    }
}

这个可以运行。对于每个字段来说,这相当容易做到,因为我没有显示太多的字段进行展示。谢谢。 - Marsharks
这将生成一个属性更改事件 - 这可能会触发其他操作 - 并且可能会导致不必要的数据库更新,因为您在不进行任何语义更改的情况下更改了属性的值。 - tvanfosson
3
问题的关键是找到执行这种逻辑的地方(在本例中为 OnLoaded());这个方法本身也可以很容易地包含 "_FirstName = _FirstName.Trim();",以避免触发属性更改事件。 - Chris Shaffer
那对我所需的可能是个不错的想法,因为我无法更改数据库架构。我真的只将这个类用作数据对象来保存数据库记录的值。如果我能拦截属性加载事件就好了,但我做不到。 - Marsharks
3
请注意,只有对应此类的表具有主键时,才能使用OnLoad()方法。 - Flo

6

如果您无法更改模式,您可能希望将设计师生成的访问器设置为私有/受保护,并在局部类实现中创建公共访问器以作为属性的前端。然后,您可以在获取访问器中修剪该值。

public partial class Contact
{

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

    ...
}

1
这是一个好的解决方案,因为这些字段不仅是char类型,而且被称为First_Name。因此,我可以修复所有字段,而无需在我的对象设计师中进行更改。 - Marsharks
问题在于当我创建一个查询并尝试使用像FullName = c.FirstName + ' ' + c.LastName这样的东西时,我会收到“无法翻译表达式并且无法将其视为本地表达式”的消息。 - Marsharks
一旦完成了筛选,您可以使用ToList()生成实际查询,然后在结果列表上执行选择。由于此时它们是对象,因此FullName的构建应该有效。 - tvanfosson
我使用的是轻量级对象,而不是返回列表。这是导致问题的那一行代码:ContactName = act.PhoneContact.FirstName + " " + act.PhoneContact.LastName - Marsharks

1
Contact contact = db.Contacts.Single(c => c.Id.Trim() == myId);

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


我认为问题不在于Id字段。 - tvanfosson
1
@tvanfosson - 我认为原帖只是举例子,并不是字面意思。 - Ralph Willgoss
1
@threadster,您链接的是Entity Framework使用的Entity SQL,它使用LINQ to Entities。而旧版EF ORM使用的是LINQ to SQL。 - Richard

1

这取决于您对模式和代码的控制程度。

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

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

但是,如果您实际上想要在某个时候保留前导或尾随空格,则可能会出现潜在问题。

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

如果您无法这样做,那么我最后的建议是编写某种工厂类,将创建的对象传递给它,并根据您想要的规则进行清理。


0

在尝试搜索马丁之前,您可以在联系人列表上运行ForEach

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

但是,如果需要为多个字段完成此操作,则这种方式并不容易维护。


1
如果他有10万个联系人会发生什么? - Ralph Willgoss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接