0

如果我有一个 LINQ to SQL 表,其中有一个名为 Alias 的字段。

然后有一个名为 OnAliasChanging(string value); 的方法存根;

我要做的是抓取值,检查数据库中值是否已经存在,然后将值设置为已经输入的值。

所以我可能会将我的别名从“griegs”更改为“slappy”,如果 slappy 存在,那么我想恢复为“griegs”的现有值。

所以我有;

    partial void OnaliasChanging(string value)
    {
        string prevValue = this.alias;
        this.Changed = true;
    }

当我检查 prevValue 的值时,它始终为空。

如何获取字段的当前值?

更新

如果我实现类似的东西;

    partial void OnaliasChanging(string value)
    {
        if (this.alias != null)
            this.alias = "TEST VALUE";
    }

它进入一个不健康的无限循环。

如果我检查别名是否已经==“TEST VALUE”,则无限循环仍然保留,因为该值始终是原始值。

有没有办法做到这一点?

4

2 回答 2

1

您发布的代码片段并不能合理地解释为什么您最终会出现无限循环。我认为这this.alias可能是一个属性,而不是字符外壳所暗示的字段,但需要查看更多内容。如果它是一个属性,那么您是OnAliasChanging在设置属性之前调用该方法;因此,尝试以相同的方法再次设置它总是会导致无限循环。通常设计这个场景的方法是在你的派生中实现一个Cancel属性OnXyzChanging EventArgs,或者在方法中保存旧值,如果你不能使用第一个(更好的)选项OnXyzChanging,然后在方法中执行检查/回滚。OnXyzChanged

但是,从根本上说,您尝试做的不是很好的设计,而且特别违反了 Linq to SQL 的原则。Linq to SQL 实体应该是一个 POCO,根本不知道兄弟实体或底层数据库。对每个属性更改执行重复检查不仅需要访问DataContextor SqlConnection,而且还会导致技术上所谓的副作用(打开新的数据库连接和/或静默丢弃属性更改)。这种设计只会让路上发生神秘的车祸。

DataContext实际上,您的特定场景是首先使该类可扩展的主要原因之一。这种类型的操作属于那里。假设这里的实体是User用 table调用的Users

partial class MyDataContext
{
    public bool ChangeAlias(Guid userID, string newAlias)
    {
        User userToChange = Users.FirstOrDefault(u => u.ID == userID);
        if ((userToChange == null) || Users.Any(u => u.Alias == newAlias))
        {
            return false;
        }
        userToChange.Alias = newAlias;

        // Optional - remove if consumer will make additional changes
        SubmitChanges();

        return true;
    }
}

这封装了您要执行的操作,但不阻止消费者Alias直接更改属性。 如果你能忍受这个,我会停在那里- 你的数据库本身应该仍然有一个 UNIQUE 约束,所以这个方法可以简单地记录下来并用作尝试更改名称的安全方法,而不会在以后冒违反约束的风险on (尽管总是存在一些风险 - 您仍然可以有竞争条件,除非您将这一切都放入事务或存储过程中)。

如果您绝对必须限制对基础属性的访问,一种方法是隐藏原始属性并制作只读包装器。在 Linq 设计器中,单击Alias属性,然后在属性表上,将Access toInternalName更改为AliasInternal(但不要触摸Source!)。最后,为实体创建一个部分类(我会在与部分类相同的文件中执行此操作MyDataContext)并为该属性编写一个只读包装器:

partial class User
{
    public string Alias
    {
        get { return AliasInternal; }
    }
}

您还必须将我们方法中的Alias引用更新为.ChangeAliasAliasInternal

请注意,这可能会破坏尝试在新Alias包装器上过滤/分组的查询(我相信 Linq 会抱怨它找不到 SQL 映射)。该属性本身可以作为访问器正常工作,但如果您需要在 上执行查找,Alias那么您可能需要另一个GetUserByAlias帮助方法 in MyDataContext,它可以在AliasInternal.

当您决定除了域逻辑之外还想弄乱 Linq 的数据访问逻辑时,事情开始变得有点冒险,这就是为什么我在上面建议您只保留该Alias属性并适当地记录其使用情况。Linq 是围绕乐观并发设计的;通常,当您需要在应用程序中强制执行 UNIQUE 约束时,您会等到实际保存更改后再处理约束冲突(如果发生)。如果您想立即执行此操作,您的任务就会变得更加困难,这就是这种冗长和普遍笨拙的原因。

再一次 - 我建议不要创建只读包装器的额外步骤;无论如何,我已经提供了一些代码,以防您的规范出于某种原因需要它。

于 2009-12-23T00:52:05.337 回答
0

是否因为 OnaliasChanging 在初始化期间触发而挂起,所以您的支持字段(别名)永远不会被初始化,所以它始终为空?

没有更多的上下文,这就是我听起来的样子。

于 2009-12-23T00:33:01.687 回答