使用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 集合中。如果没有设置字符串的格式,将为每个数据字段创建两个同名参数。通过更改原始值参数的名称,可以将数据与原始数据源进行比较,以检测冲突并比较键值。

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值