代码之家  ›  专栏  ›  技术社区  ›  griegs

LINQ to SQL表扩展性方法

  •  0
  • griegs  · 技术社区  · 15 年前

    如果我有一个LINQ to SQL表,它有一个名为say alias的字段。

    然后有一个方法存根称为OniasChanging(字符串值);

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

    因此,我可能将别名从“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";
        }
    

    它进入了一个不健康的内隐循环。

    如果我包括一个检查,看看alias是否已经==“test value”,那么内插循环仍然保持不变,因为该值始终是原始值。

    有办法吗?

    2 回复  |  直到 15 年前
        1
  •  1
  •   Aaronaught    15 年前

    你发布的代码片段并不能解释为什么你最终会得到一个无限循环。我在想 this.alias 可能是一个属性,而不是字符大小写所暗示的字段,但需要了解更多信息。如果它是一个属性,那么您将调用 OnAliasChanging 方法;因此,尝试在同一方法中再次设置该属性将始终导致无限循环。通常,设计此方案的方法是实现 Cancel 您的财产 OnXyzChanging EventArgs 派生,或将旧值保存在 ONXYZ悬挂 方法,然后在 OnXyzChanged 方法,如果不能使用第一个(更好的)选项。

    不过,从根本上讲,您要做的工作通常不是很好的设计,并且具体地违背了LinqToSQL的原则。LINQtoSQL实体应该是一个POCO,根本不知道兄弟实体或底层数据库。要对每个属性更改执行重复检查,不仅需要访问 DataContext SqlConnection ,但也会导致技术上称为副作用(打开新的数据库连接和/或静默放弃属性更改)。这种设计只会让神秘的撞车声尖叫。

    事实上,您的特定场景是 数据上下文 类最初是可扩展的。这种类型的操作属于那里。假设这里的实体被称为 User 带表 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 直接属性。 如果你能忍受的话,我就停在那里 -您应该在数据库本身中仍然有一个唯一的约束,所以这个方法可以简单地记录下来并作为 安全的 尝试名称更改而不冒稍后违反约束的风险的方法(尽管 一些 风险-除非将所有这些都放入事务或存储过程中,否则您仍然可以具有争用条件)。

    如果你真的 必须 限制对基础属性的访问,一种方法是隐藏原始属性并生成只读包装。在Linq设计器中,单击 别名 属性,并在属性表上更改 通路 Internal 以及 姓名 AliasInternal (但不要触摸 来源 !)最后,为实体创建一个分部类(我将在与 MyDataContext 并为属性编写只读包装:

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

    您还必须更新 别名 我们的参考文献 ChangeAlias 方法到 别名内部 .

    请注意,这可能会中断尝试对新的 别名 包装器(我相信Linq会抱怨它找不到SQL映射)。属性本身作为访问器可以正常工作,但是如果需要在 别名 那么你可能需要另一个 GetUserByAlias 中的Helper方法 MyDATA文本 ,可以在 别名内部 .

    当您决定除了域逻辑之外还要处理LINQ的数据访问逻辑时,事情开始变得有点不确定,这就是为什么我上面建议您只保留 别名 仅属性,并适当记录其用法。Linq是围绕乐观并发性设计的;通常,当您需要在应用程序中强制一个唯一的约束时,您需要等到实际保存了更改,然后处理发生的约束冲突。如果你想马上做,你的任务就变得更难了,这就是你冗长而笨拙的原因。

    再来一次-我建议 反对 创建只读包装器的附加步骤;无论如何,我都会提供一些代码,以防您的规范出于某种原因需要它。

        2
  •  0
  •   µBio    15 年前

    它是否因为在初始化过程中触发了OniasChanging而挂起,所以您的支持字段(别名)从未初始化过,所以始终为空?

    如果没有更多的背景,这就是我的感觉。

    推荐文章