FreeSql icon indicating copy to clipboard operation
FreeSql copied to clipboard

IsRowversion设置数据库伪列报错问题!

Open worldofchu opened this issue 4 years ago • 14 comments

问题描述及重现步骤:

pg数据库,设置xmin伪列作为乐观锁字段,然后update报错,发现set xmin=。。。 实体特性本身也设置了canupdate为false。 建议!IsRowversion 增加开关量设置 可以使rowversion字段不参与update的set。 因为 例如sqlserver pg 都有对应的伪列进行乐观锁,oracle也有不太严谨的orarowscn,sqlserver更是专门的timestamp类型。

请求作者 进行 IsRowversion 增加开关量设置 可以使rowversion字段不参与update的set。 谢谢!

数据库的具体版本

pg12+

安装的包


.net framework/. net core? 及具体版本

net6

worldofchu avatar Jul 19 '21 01:07 worldofchu

请问作者 何时能更正#825 啊 ,想尽早使用!谢谢!

worldofchu avatar Aug 08 '21 12:08 worldofchu

请问作者 何时能更正#825 啊 ,想尽早使用!谢谢!!!!+1

worldofchu avatar Aug 18 '21 08:08 worldofchu

考虑每个数据库标准不同,伪劣暂时不支持。

2881099 avatar Aug 28 '21 12:08 2881099

现在支持 int/long 以及 byte[]

2881099 avatar Aug 28 '21 12:08 2881099

可否放开个口子呢,类似 比如注解或者flunetapi 加个布尔参数,来使得 指定字段 insert 和update时不set值,但是指定字段 在select时刻和where 如现在一样的rowversion表现即可????

worldofchu avatar Aug 30 '21 05:08 worldofchu

环境: sql server 2008r2

[FreeSql.DataAnnotations.Column(CanUpdate = false, CanInsert = false)] 就可以不更新此列了

sdwdjzhy avatar Oct 28 '21 08:10 sdwdjzhy

我今天验证了下, _tbrepo.Orm.Update<Tb>().SetSource(tb111).ExecuteAffrows(); 使用了freesql 2.6.1版本和 postgresql12+ 字段都设置了canupdate caninsert false 但是上述语句不生效!!!还是不行的!

worldofchu avatar Nov 04 '21 00:11 worldofchu

当然 我同时设置了 .IsVersion(true)

worldofchu avatar Nov 04 '21 01:11 worldofchu

没用过 pg,我用的是 sql server


    /// <summary>
    /// tAd
    /// </summary>
    [DbTable]
    [DisplayName("tTest")]
    public partial class tTest
    { 

        /// <summary>
        /// 编号
        /// </summary>
        [Display(Name = "编号")]
        [Key]
        [System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
#if NET5_0_OR_GREATER
        [FreeSql.DataAnnotations.Column(CanInsert = true, CanUpdate = true)]
#endif
        public int Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        [Display(Name = "名称")]
        [StringLength(255, MinimumLength = 0)]
        [Required(ErrorMessage = "名称 - 不能为空")]
        public string Name { get; set; }

        /// <summary>
        /// RowVersion
        /// </summary>
        [Display(Name = "RowVersion")]
        [Timestamp]
#if NETCOREAPP3_1 || NET5_0
        [FreeSql.DataAnnotations.Column(CanUpdate = false, CanInsert = false)]
#endif
        public byte[] RowVersion { get; set; }

使用

        public async Task<IActionResult> Test()
        {
            var test = await freesql.Select<tTest>().FirstAsync();

            await freesql.Update<tTest>(test).Set(i => i.Name, "bbb").ExecuteAffrowsAsync();
            return Ok("dddd");

        }

刚刚测试过,没有问题,可以更新的。 但是如果加上 了 IsVersion = true, 就抛出异常了

System.Exception: 不能更新时间戳列。
 ---> Microsoft.Data.SqlClient.SqlException (0x80131904): 不能更新时间戳列。

所以,你试试不加 IsVersion = true,会不会成功

sdwdjzhy avatar Nov 04 '21 01:11 sdwdjzhy

sqlserver 的Timestamp 字段多么完美!!你为啥非得不用呢?目的不就是为了 使用它么(使用它作为rowversion)

worldofchu avatar Nov 04 '21 02:11 worldofchu

没办法啊,他又不支持 Timestamp 自动绑定where

await freesql.Update<tTest>(test).Where(i => i.Id == test.Id && i.RowVersion == test.RowVersion).Set(i => i.Name, "ccc").ExecuteAffrowsAsync();

那就手动加上 RowVersion 的where呗。 反正不能加 IsVersion = true,加了就报错

sdwdjzhy avatar Nov 04 '21 02:11 sdwdjzhy

手动加 我何必使用 不够麻烦的。其实源代码也能改,但是我们无法长期保持跟进。

worldofchu avatar Nov 04 '21 02:11 worldofchu

其实源码 FreeSql-2.6.100\FreeSql\Internal\CommonProvider.cs文件 第790行代码 if (_table.VersionColumn != null) 修正为 if (_table.VersionColumn != null&& _table.VersionColumn.Attribute.CanUpdate) 理论上就行了。。不过我没test

worldofchu avatar Nov 04 '21 06:11 worldofchu

考虑每个数据库标准不同,伪劣暂时不支持。

--恳请作者再次考虑下,其实只是在 Updatesql 在遇到VersionColumn 字段时刻考虑一下该字段是否canupdate即可 本身这个字段默认为true,也不影响默认效果。 但是 ,其他有需要的开发者就可以 在model配置时刻设置 某字段为rowversion和canupdate=false 从而满足这种需求且不影响 原本的默认行为!!! @2881099

worldofchu avatar Nov 04 '21 06:11 worldofchu

其实不用太纠结,freesql考虑更多数据库通用,TableInfo VersionColumn 可以通过反射修改的。

2881099 avatar Oct 02 '22 16:10 2881099