导航

Chapter Data Modification & Chapter Data Validation

Posted on 2015-10-14 10:43  木儿壳子  阅读(262)  评论(0编辑  收藏  举报

Chapter Data Modification

 

XF的数据提交,支持单行、集合和多层次的master-details结构的数据。

 

Create

当提交如下数据

  <Job>

    <Id/>

    <Name>CEO</Name>

    <Allowance>1000</Allowance>

    <Descr/>

  </Job>

Create方法在数据库表Jobs中插入一条返回数据。注意,提交的数据中没有提供Id的值,

表示Id字段为自增长或取自序列Sequence值(在schema Field <Id>指定)。

也可以在提交数据中设置Id的值,显然,对于自增长字段,设置了也无效,但会优先于序列Sequence,也就是,设置了Id的值,就不会去序列取值了。

 

多层master-details举例:

  <Job>

    <Id/>

    <Name>Clerk</Name>

    <Allowance>0</Allowance>

    <Descr/>

    <Employees>

      <Employee>

        <Id/>

        <Name>John Smith</Name>

        <Users>

          <User>

            <Id/>

            <UserName>John</UserName>

          </User>

        </Users>

      </Employee>

      <Employee>

        <Id/>

        <Name>Michael Gill</Name>

        <Users>

          <User>

            <Id/>

            <UserName>Gill</UserName>

          </User>

        </Users>

      </Employee>

    </Employees>

  </Job>

同样,方法结束,所有的Id值都会填入。

 

多对多:

  <User>

    <Id/>

    <UserName>Carl</UserName>

    <Roles>

      <Role>

        <Id>1</Id>

        ...

      </Role>

      <Role>

        <Id>2</Id>

        ...

      </Role>

    </Roles>

  </User>

同样符合多对多“短路”规则,如果<Role>再内嵌一个集合(Set),将被丢弃。

 

提交数据如果存在计算字段或外表字段(如:<Job.Name>CTO</Job.Name>),将被丢弃。

 

Delete

 

XF在删除master-details结构的details时,与EF一样,会根据schemadetail的关系字段(外键字段)是否为空,来决定是删除行,还是设置关系字段为空。

例如:

  <Job>

    ...

    <Employees>

      <Employee>

        ...

      </Employee>

      ...

    </Employees>

  </Job>

如果Employees表中字段JobId允许为空,不是Delete Employees…,而是Update Set JobId = NULL…,因此,Delete方法会触发Updating事件。

 

Update

Update master-details结构的数据时,相当于“Put”。

如通过并发检查,Update会强制同步数据库相应的数据行为提交数据,也就是说对于details,会和数据库相应数据进行比较,

如果数据库中不存在就Insert,反之就是Update,数据库存在而提交数据中不存在的则删除。因此,不但会触发Updating事件,也可能触发InsertingInsertedDeleting事件。

 

UpdateUpdateWithOriginal

 

考虑一个典型的Update场景,首先获取需要编辑的(层次master-details)原始数据,然后(一般有个UI)进行修改,

最后把修改完的数据提交保存(上述Update方法)。如果,不光提交修改后的数据还把开始获取的原始数据一并提交,

就需要用到UpdateUpdateWithOriginal,这里的Original就是指原始数据。

 

Update方法类似,不同的是UpdateUpdateWithOriginal比较的数据不再是数据库中的数据,而是Original

 

事务包

所谓事务包就是把一系列方法调用打包在一个<Transaction>里面,这一系列方法在同一事务内执行。

XFElementContext.SaveChanges(XElement packet)方法保存事务包。

 

事务包举例如下:

  <Transaction>

    <Create Schema="Membership">

      <Users>

        <User>

          ...

        </User>

      </Users>

    </Create>

    <Delete>

      <Role>

        ...

      </Role>

    </Delete>

    <Update Schema="Membership" Config="Staff">

      <Config Name="Staff" Version="1.2.3">

        ...

      </Config>

      <Employee>

        ...

      </Employee>

      <Employee Original="True">

        ...

      </Employee>

    </Update>

  </Transaction>

 

<Create Schema="Membership"> 指定使用名为MembershipNamedSchema

<Update Schema="Membership" Config="Staff"> 指定使用名为MembershipNamedSchema,并且内嵌一个NameStaffmodifying schema

<Employee Original="True"> 指出调用的是UpdateWithOriginal。调用Update方法,不需要<Employee Original="True">

 

 

事务

上述方法都会自己管理事务。如果业务足够复杂,要编写代码启动事务,需按下列示意代码编写:

 

                      ElementContext elementContext = ...;

                  

            elementContext.Database.Connection.Open();

            elementContext.Database.Transaction = elementContext.Database.Connection.BeginTransaction();

            try

            {

              

                                      ...

                elementContext.Database.Transaction.Commit();

                  

            }

            catch

            {

                elementContext.Database.Transaction.Rollback();

                throw;

            }

            finally

            {

                elementContext.Database.Connection.Close();

                elementContext.Database.Transaction = null;

            }

 

 

并发

XFEF一样,通过下面2Attribute来控制(数据库行)并发:

TimestampAttribute

ConcurrencyCheckAttribute

DeleteUpdate每个数据库行时,会检查上述2Attribute标记的字段的值和数据库当前值是否一致,如不一致,则抛出ConcurrencyCheckException异常。

 

事件

ElementContext有四个事件:

Inserting 在插入数据行时发生,

事件参数的Node属性,就是将要插入数据库的行数据。这时还未插入数据库,是最后修改Node的机会。下面~ing事件同。

 

Inserted 在插入数据行后发生

事件参数的Node属性,是插入数据库后的行数据。这时自增长或取自序列的Id,已经回插到Node中。

事件参数的After属性,允许添加一组Sql,在插入后执行。相当数据库的After行触发器。

 

Deleting 在删除数据行时发生

事件参数的Before属性,相当数据库的After行触发器。

 

Updating 在更改数据行时发生

事件参数有AfterBefore属性。

 

 

Chapter Data Validation

 

在每个Element提交数据库前,都会对其验证,验证失败时,抛出ElementValidationException异常(内部封装ElementValidationResult[])。

 

当然,也可以调用ElementContext.GetValidationResults(…)来返回ElementValidationResult[],不提交数据库而直接验证。

 

XF验证完全仿照EF,支持下列Attribute,均继承自System.ComponentModel.DataAnnotations.ValidationAttribute

CustomValidationAttribute

DataTypeAttribute

RangeAttribute

RegularExpressionAttribute

RequiredAttribute

StringLengthAttribute

 

MaxLengthAttribute

MinLengthAttribute

CreditCardAttribute

EmailAddressAttribute

PhoneAttribute

UrlAttribute

 

也可能会用到(如果配置的话):

DisplayNameAttribute

DisplayAttribute

 

EF中,典型的类定义:

    public class User

    {

        [Key]

        public int Id { get; set; }

 

        [DisplayName("用户名")]

        [Required(AllowEmptyStrings = true)]

        [MinLength(6)]

        public string UserName { get; set; }

 

        [DisplayName("密码")]

        [Required(AllowEmptyStrings = true)]

        [MinLength(6)]

        public string Password { get; set; }

        

         ...

}

 

XF相应的配置(在schema中)如下:

  <User Set="Users">

    <Id>

      <key/>

    </Id>

    <UserName>

      <DisplayName>

        <DisplayName>用户名</DisplayName>

      </DisplayName>

      <Required>

        <AllowEmptyStrings>True</AllowEmptyStrings>

      </Required>

      <MinLength>

        <Length>4</Length>

      </MinLength>

    </UserName>

    <Password>

      <DisplayName>

        <DisplayName>密码</DisplayName>

      </DisplayName>

      <Required>

        <AllowEmptyStrings>True</AllowEmptyStrings>

      </Required>

      <MinLength>

        <Length>6</Length>

      </MinLength>

</Password>

  </User>

 

注:SQL Server 需设置<AllowEmptyStrings>True</AllowEmptyStrings>

 

除此之外,事件ElementContext.Validating 也会在验证Element时发生。

 

ValidationAttribute不足以应付的复杂或特殊的业务规则可以在此通过写代码来验证,

在事件参数ValidatingEventArgs中的ValidationResults添加未通过验证的ValidationResult