• 使用Subsonic与ObjectDataSource(ODS)



       Subsonic,在小型项目应用中,作为数据库访问层相当方便,而很多快速开发中我们一般会使用GridView + ObjectDataSrouce ,基本上是一拖一放就能解决很多问题,当然如果你平时注意收据一些样式或皮肤文件,那么做出来的界面也很不错,总之一句话,"太方便了!".

      一般使用SubStage生成代码后,每张表,如名为:Rule的表会生成一个叫RuleController的来,这个来是用来绑定ODS用的,

     下面是生成Rule表的Update方法,
            [DataObjectMethod(DataObjectMethodType.Update, true)]
         public void Update(int Id,string Name,string ReplaceText,string ReplaceMode,string Pattern,bool? IsRegex,bool? Enabled,string Username)
         {
          Rule item = new Rule();
             item.MarkOld(); //设置为更新模式,即IsNew=false; IsLoaded=True,这样save时对应的SQL为Update
             item.IsLoaded = true; //貌似这句跟上面一样
         
       item.Id = Id;
        
       item.Name = Name;
        
       item.ReplaceText = ReplaceText;
        
       item.ReplaceMode = ReplaceMode;
        
       item.Pattern = Pattern;
        
       item.IsRegex = IsRegex;
        
       item.Enabled = Enabled;
        
       item.Username = Username;
        
             item.Save(UserName);
         }

     可以看到Update方法中的参数列表跟数据库中表的列1,1对应,一般情况下我们不会在gridview中包括全部列,如文章内容列这些不会在gridview中显示,而是放到一个专门的页面上来处理,那么粗看Update代码也许会有这样的困惑:

    我在gridview上只双向帮定(bind) Name(参考上面代码),IsRegex 两个列,其他列要么不显示,要么只读(注意Id为主键,页面上的geidview 设置DataKeyNames="ID"),这样每次触发Update时,gridview只把双向帮定的数据跟ID发给ODS,而其他列多为null,那么Update 中的item.Save(UserName)会不会出现把数据库中不需要更新的列设置为null呢?

      在使用数据库跟踪后发现没有出现我上面担心问题,subsonic生成的update一般为 update [表名] Set 双向绑定列1=value1,双向绑定列2=value2... Where Id=valueid.  查找项目提供的代码发现,设置属性时(如item.Username=Username)会调用定义在RecordBase.cs中的SetColumnValue(string columnName,object oValue)来进行,代码如下

    -------------------------------------

      public void SetColumnValue(string columnName, object oValue)
            {
                columnSettings = columnSettings ?? new TableSchema.TableColumnSettingCollection();

                // add the column to the DirtyColumns
                // if this instance has already been loaded
                // and this is a change to existing values
                if(IsLoaded && !IsNew)
                {
                    TableSchema.Table schema = GetSchema();
                    object oldValue = null;
                    string oldValueMsg = "NULL";
                    string newValueMsg = "NULL";
                    bool areEqualOrBothNull = false;

                    try
                    {
                        oldValue = columnSettings.GetValue(columnName);
                    }
                    catch {}

                    if(oldValue == null && oValue == null)
                        areEqualOrBothNull = true;
                    else
                    {
                        if(oldValue != null)
                        {
                            oldValueMsg = oldValue.ToString();
                            areEqualOrBothNull = oldValue.Equals(oValue);
                        }

                        if(oValue != null)
                            newValueMsg = oValue.ToString();
                    }

                    TableSchema.TableColumn dirtyCol = schema.GetColumn(columnName);

                    if(dirtyCol != null && !areEqualOrBothNull)
                    {
                        string auditMessage = String.Format("Value changed from {0} to {1}{2}", oldValueMsg, newValueMsg, Environment.NewLine);
                        TableSchema.TableColumn dirtyEntry = DirtyColumns.GetColumn(columnName);
                        if(dirtyEntry != null)
                        {
                            DirtyColumns.Remove(dirtyEntry);
                            auditMessage = String.Concat(dirtyCol.AuditMessage, auditMessage);
                        }

                        dirtyCol.AuditMessage = auditMessage;
                        DirtyColumns.Add(dirtyCol);
                    }
                }

                columnSettings.SetValue(columnName, oValue);
            }

    ------------------------------

     从上面代码可以看到,当传入的oValue为null,并且oldValue也为null时,ActiveRecord是不会把这个列加入到DirtyColumns中的,而DirtyColumns中的列则是生成SQL语句Update 中 Set 后具体更新的列.  RuleController(参考上面)中的Update中首先Rule item= new Rule() 这样的结果是全部列的oldValue也为null(因为Rule为参构造函数创建类后不会进行读书记库操作,因此columnSettings中的全部列值多为null,这样就保证Save时不会把null列覆盖到原来的列, 另外要注意的是,为了保证能把null专递到 RuleController的Update中,Update的值类型参数多为可空类型(如?int,?bool...) 这样当gridview没传递相应列值时---没双向绑定或不是主键(也有可能是没在gridview中设置)ODS就会根据配置的参数列表传递一个null过去.

        另外你可以在ODS的Updateing ,Selecting事件中设置具体的参数值,在gridview + ods + 数据访问类 这样的三层结构中,数据需要层层传递,同时也意味着一个修改或说控制可以安排在这三层的任意一层,前面两层一般使用控件提供的事件而最后一层是自己编写的类.

     最后一般注意下ODS的OldValuesParameterFormatString 设置,在使用subsonic时设置为{0},
    下面为MSDN的描述:

    OldValuesParameterFormatString 格式字符串只应用于主键,例如,由相关联的数据绑定控件的 DataKeyNames 属性所标识的主键,或者用在以下删除方案和更新方案中:ConflictDetection 属性设置为 CompareAllValues 值,并且一组 oldValues 值传递给了相应的数据方法。这种情况下,此格式字符串应用于 oldValues 集合中的每个参数名。

    在以下两种常见方案中,您可能要更改 OldValuesParameterFormatString 属性:

    • 在更新中区别旧值和新值。ConflictDetection 属性设置为 CompareAllValues 值时,原始值和新值的参数都被添加到 UpdateParameters 集合中。如果没有设置字符串的格式,将为每个数据字段创建两个同名参数。通过更改原始值参数的名称,可以将数据与原始数据源进行比较,以检测冲突并比较键值。

    • 某些可视化设计器实现了特定的原始值和键命名方案。

  • 相关阅读:
    KMeans算法分析以及实现
    决策树(ID3,C4.5,CART)原理以及实现
    [推荐系统读书笔记]利用用户标签数据
    [推荐系统读书笔记]推荐系统冷启动问题
    [推荐系统]利用用户行为数据
    [推荐系统读书笔记]好的推荐系统
    Docker Hub国内镜像加速
    ubuntu下cannot connect to X server :1
    vscode编写C++设置左花括号不换行
    SLAM十四讲中Sophus库安装
  • 原文地址:https://www.cnblogs.com/wdfrog/p/1351229.html
Copyright © 2020-2023  润新知