mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 18:52:50 +08:00
- 增加 IsVersion string 字符串乐观锁;#1178
This commit is contained in:
parent
a219b39e5f
commit
84cfa65281
@ -311,9 +311,9 @@ namespace base_entity
|
||||
//.UseConnectionString(FreeSql.DataType.Firebird, @"database=localhost:D:\fbdata\EXAMPLES.fdb;user=sysdba;password=123456;max pool size=5")
|
||||
|
||||
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=2")
|
||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=2")
|
||||
|
||||
.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
|
||||
//.UseConnectionString(FreeSql.DataType.SqlServer, "Data Source=.;Integrated Security=True;Initial Catalog=freesqlTest;Pooling=true;Max Pool Size=3;TrustServerCertificate=true")
|
||||
|
||||
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=tedb;Pooling=true;Maximum Pool Size=2")
|
||||
//.UseConnectionString(FreeSql.DataType.PostgreSQL, "Host=192.168.164.10;Port=5432;Username=postgres;Password=123456;Database=toc;Pooling=true;Maximum Pool Size=2")
|
||||
@ -344,6 +344,8 @@ namespace base_entity
|
||||
BaseEntity.Initialization(fsql, () => _asyncUow.Value);
|
||||
#endregion
|
||||
|
||||
var sqlToYear = fsql.Select<User1>().ToSql(a => a.CreateTime.Year);
|
||||
|
||||
TestExp(fsql);
|
||||
|
||||
fsql.CodeFirst.GetTableByEntity(typeof(TestComment01));
|
||||
|
@ -12,6 +12,131 @@ namespace FreeSql.Tests.SqlServer
|
||||
{
|
||||
public class SqlServerCodeFirstTest
|
||||
{
|
||||
[Fact]
|
||||
public void VersionInt()
|
||||
{
|
||||
var fsql = g.sqlserver;
|
||||
fsql.Delete<VersionInt01>().Where("1=1").ExecuteAffrows();
|
||||
var item = new VersionInt01 { name = "name01" };
|
||||
fsql.Insert(item).ExecuteAffrows();
|
||||
|
||||
item = fsql.Select<VersionInt01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.Equal(0, item.version);
|
||||
|
||||
item.name = "name02";
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = @p_0, [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}') AND [version] = 0", fsql.Update<VersionInt01>().SetSource(item).ToSql());
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = N'name02', [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}') AND [version] = 0", fsql.Update<VersionInt01>().SetSource(item).NoneParameter().ToSql());
|
||||
Assert.Equal(1, fsql.Update<VersionInt01>().SetSource(item).ExecuteAffrows());
|
||||
item = fsql.Select<VersionInt01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.Equal("name02", item.name);
|
||||
Assert.Equal(1, item.version);
|
||||
|
||||
item.name = "name03";
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = @p_0, [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}') AND [version] = 1", fsql.Update<VersionInt01>().SetSource(item).ToSql());
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = N'name03', [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}') AND [version] = 1", fsql.Update<VersionInt01>().SetSource(item).NoneParameter().ToSql());
|
||||
Assert.Equal(1, fsql.Update<VersionInt01>().SetSource(item).ExecuteAffrows());
|
||||
item = fsql.Select<VersionInt01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.Equal("name03", item.name);
|
||||
Assert.Equal(2, item.version);
|
||||
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = @p_0, [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}')", fsql.Update<VersionInt01>().Set(a => a.name, "name04").Where(a => a.id == item.id).ToSql());
|
||||
Assert.Equal($@"UPDATE [VersionInt01] SET [name] = N'name04', [version] = isnull([version], 0) + 1
|
||||
WHERE ([id] = '{item.id}')", fsql.Update<VersionInt01>().NoneParameter().Set(a => a.name, "name04").Where(a => a.id == item.id).ToSql());
|
||||
Assert.Equal(1, fsql.Update<VersionInt01>().Set(a => a.name, "name04").Where(a => a.id == item.id).ExecuteAffrows());
|
||||
item = fsql.Select<VersionInt01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.Equal("name04", item.name);
|
||||
Assert.Equal(3, item.version);
|
||||
}
|
||||
class VersionInt01
|
||||
{
|
||||
public Guid id { get; set; }
|
||||
public string name { get; set; }
|
||||
[Column(IsVersion = true)]
|
||||
public int version { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VersionBytes()
|
||||
{
|
||||
bool LocalEqualsVersion(byte[] v1, byte[] v2)
|
||||
{
|
||||
if (v1.Length == v2.Length)
|
||||
{
|
||||
for (var y = 0; y < v2.Length; y++)
|
||||
if (v1[y] != v2[y]) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var fsql = g.sqlserver;
|
||||
fsql.Delete<VersionBytes01>().Where("1=1").ExecuteAffrows();
|
||||
var item = new VersionBytes01 { name = "name01" };
|
||||
fsql.Insert(item).ExecuteAffrows();
|
||||
var itemVersion = item.version;
|
||||
Assert.NotNull(itemVersion);
|
||||
|
||||
item = fsql.Select<VersionBytes01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.True(LocalEqualsVersion(itemVersion, item.version));
|
||||
|
||||
item.name = "name02";
|
||||
var sql = fsql.Update<VersionBytes01>().SetSource(item).ToSql();
|
||||
Assert.Equal(1, fsql.Update<VersionBytes01>().SetSource(item).ExecuteAffrows());
|
||||
|
||||
item.name = "name03";
|
||||
Assert.Equal(1, fsql.Update<VersionBytes01>().SetSource(item).ExecuteAffrows());
|
||||
|
||||
Assert.Equal(1, fsql.Update<VersionBytes01>().Set(a => a.name, "name04").Where(a => a.id == item.id).ExecuteAffrows());
|
||||
}
|
||||
class VersionBytes01
|
||||
{
|
||||
public Guid id { get; set; }
|
||||
public string name { get; set; }
|
||||
[Column(IsVersion = true)]
|
||||
public byte[] version { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VersionString()
|
||||
{
|
||||
var fsql = g.sqlserver;
|
||||
fsql.Delete<VersionString01>().Where("1=1").ExecuteAffrows();
|
||||
var item = new VersionString01 { name = "name01" };
|
||||
fsql.Insert(item).ExecuteAffrows();
|
||||
var itemVersion = item.version;
|
||||
Assert.NotNull(itemVersion);
|
||||
|
||||
item = fsql.Select<VersionString01>().Where(a => a.id == item.id).First();
|
||||
Assert.NotNull(item);
|
||||
Assert.Equal(itemVersion, item.version);
|
||||
|
||||
item.name = "name02";
|
||||
var sql = fsql.Update<VersionString01>().SetSource(item).ToSql();
|
||||
Assert.Equal(1, fsql.Update<VersionString01>().SetSource(item).ExecuteAffrows());
|
||||
|
||||
item.name = "name03";
|
||||
Assert.Equal(1, fsql.Update<VersionString01>().SetSource(item).ExecuteAffrows());
|
||||
|
||||
Assert.Equal(1, fsql.Update<VersionString01>().Set(a => a.name, "name04").Where(a => a.id == item.id).ExecuteAffrows());
|
||||
}
|
||||
class VersionString01
|
||||
{
|
||||
public Guid id { get; set; }
|
||||
public string name { get; set; }
|
||||
[Column(IsVersion = true)]
|
||||
public string version { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_0String()
|
||||
{
|
||||
|
@ -734,7 +734,8 @@ namespace FreeSql.Tests
|
||||
.ToList(a => new
|
||||
{
|
||||
a.Key,
|
||||
sss = a.Sum(a.Value.Item1.OptionsEntity04)
|
||||
sss = a.Sum(a.Value.Item1.OptionsEntity04),
|
||||
xxx = SqlExt.DistinctCount(a.Value.Item2.Title)
|
||||
});
|
||||
|
||||
|
||||
|
@ -5236,7 +5236,7 @@
|
||||
</member>
|
||||
<member name="M:FreeSql.CoreStrings.Properties_AsRowLock_Must_Numeric_Byte(System.Object)">
|
||||
<summary>
|
||||
属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[],并且不可为 Nullable
|
||||
属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[] 或者 string,并且不可为 Nullable
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:FreeSql.CoreStrings.Properties_Cannot_Null">
|
||||
|
@ -188,10 +188,22 @@ namespace FreeSql.Internal.CommonProvider
|
||||
col.SetValue(data, val = FreeUtil.NewMongodbId());
|
||||
}
|
||||
}
|
||||
if (col.Attribute.IsVersion)
|
||||
{
|
||||
if (col.Attribute.MapType == typeof(byte[]))
|
||||
{
|
||||
if (val == null || (val is byte[] bytes && bytes.Length == 0))
|
||||
col.SetValue(data, val = Utils.GuidToBytes(Guid.NewGuid()));
|
||||
}
|
||||
else if (col.Attribute.MapType == typeof(string))
|
||||
{
|
||||
var verval = col.GetDbValue(data) as string;
|
||||
if (string.IsNullOrWhiteSpace(verval))
|
||||
col.SetValue(data, val = Guid.NewGuid().ToString());
|
||||
}
|
||||
}
|
||||
if (val == null && col.Attribute.MapType == typeof(string) && col.Attribute.IsNullable == false)
|
||||
col.SetValue(data, val = "");
|
||||
if (col.Attribute.MapType == typeof(byte[]) && (val == null || (val is byte[] bytes && bytes.Length == 0)) && col.Attribute.IsVersion)
|
||||
col.SetValue(data, val = Utils.GuidToBytes(Guid.NewGuid()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
public DbConnection _connection;
|
||||
public int _commandTimeout = 0;
|
||||
public Action<StringBuilder> _interceptSql;
|
||||
public byte[] _updateVersionValue;
|
||||
public object _updateVersionValue;
|
||||
}
|
||||
|
||||
public abstract partial class UpdateProvider<T1> : UpdateProvider, IUpdate<T1>
|
||||
@ -141,6 +141,8 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
if (_versionColumn.Attribute.MapType == typeof(byte[]))
|
||||
_orm.SetEntityValueWithPropertyName(_table.Type, d, _versionColumn.CsName, _updateVersionValue);
|
||||
else if (_versionColumn.Attribute.MapType == typeof(string))
|
||||
_orm.SetEntityValueWithPropertyName(_table.Type, d, _versionColumn.CsName, _updateVersionValue);
|
||||
else
|
||||
_orm.SetEntityIncrByWithPropertyName(_table.Type, d, _versionColumn.CsName, 1);
|
||||
}
|
||||
@ -1005,6 +1007,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_updateVersionValue = Utils.GuidToBytes(Guid.NewGuid());
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, "uv", _versionColumn, _versionColumn.Attribute.MapType, _updateVersionValue));
|
||||
}
|
||||
else if (_versionColumn.Attribute.MapType == typeof(string))
|
||||
{
|
||||
_updateVersionValue = Guid.NewGuid().ToString();
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, "uv", _versionColumn, _versionColumn.Attribute.MapType, _updateVersionValue));
|
||||
}
|
||||
else
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.IsNull(vcname, 0)).Append(" + 1");
|
||||
}
|
||||
|
@ -326,6 +326,7 @@ namespace FreeSql.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (colattr.MapType == typeof(string) && colattr.IsVersion == true) colattr.StringLength = 40;
|
||||
if (colattr.MapType == typeof(byte[]) && colattr.IsVersion == true) colattr.StringLength = 16;
|
||||
if (colattr.MapType == typeof(byte[]) && colattr.StringLength != 0)
|
||||
{
|
||||
@ -395,7 +396,8 @@ namespace FreeSql.Internal
|
||||
trytb.VersionColumn = trytb.Columns.Values.Where(a => a.Attribute.IsVersion == true).LastOrDefault();
|
||||
if (trytb.VersionColumn != null)
|
||||
{
|
||||
if (trytb.VersionColumn.Attribute.MapType.IsNullableType() || trytb.VersionColumn.Attribute.MapType.IsNumberType() == false && trytb.VersionColumn.Attribute.MapType != typeof(byte[]))
|
||||
if (trytb.VersionColumn.Attribute.MapType.IsNullableType() ||
|
||||
trytb.VersionColumn.Attribute.MapType.IsNumberType() == false && !new[] { typeof(byte[]), typeof(string) }.Contains(trytb.VersionColumn.Attribute.MapType))
|
||||
throw new Exception(CoreStrings.Properties_AsRowLock_Must_Numeric_Byte(trytb.VersionColumn.CsName));
|
||||
}
|
||||
tbattr?.ParseAsTable(trytb);
|
||||
|
2
FreeSql/Properties/CoreStrings.Designer.cs
generated
2
FreeSql/Properties/CoreStrings.Designer.cs
generated
@ -827,7 +827,7 @@ namespace FreeSql
|
||||
policyName, UnavailableExceptionMessage);
|
||||
|
||||
/// <summary>
|
||||
/// 属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[],并且不可为 Nullable
|
||||
/// 属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[] 或者 string,并且不可为 Nullable
|
||||
/// </summary>
|
||||
public static string Properties_AsRowLock_Must_Numeric_Byte(object trytbVersionColumnCsName)
|
||||
=> string.Format(
|
||||
|
@ -433,7 +433,7 @@
|
||||
<value>FreeSql: The {policyName} status is unavailable and cannot be used until the background checker is restored. {UnavailableExceptionMessage}</value>
|
||||
</data>
|
||||
<data name="Properties_AsRowLock_Must_Numeric_Byte" xml:space="preserve">
|
||||
<value>FreeSql: The property {trytbVersionColumnCsName} is labeled as a row lock (optimistic lock) (IsVersion), but it must be a numeric type or byte[], and it cannot be Nullable</value>
|
||||
<value>FreeSql: The property {trytbVersionColumnCsName} is labeled as a row lock (optimistic lock) (IsVersion), but it must be a numeric type or byte[] or string, and it cannot be Nullable</value>
|
||||
</data>
|
||||
<data name="Properties_Cannot_Null" xml:space="preserve">
|
||||
<value>FreeSql: Properrties parameter cannot be empty</value>
|
||||
|
@ -433,7 +433,7 @@
|
||||
<value>【{policyName}】状态不可用,等待后台检查程序恢复方可使用。{UnavailableExceptionMessage}</value>
|
||||
</data>
|
||||
<data name="Properties_AsRowLock_Must_Numeric_Byte" xml:space="preserve">
|
||||
<value>属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[],并且不可为 Nullable</value>
|
||||
<value>属性{trytbVersionColumnCsName} 被标注为行锁(乐观锁)(IsVersion),但其必须为数字类型 或者 byte[] 或者 string,并且不可为 Nullable</value>
|
||||
</data>
|
||||
<data name="Properties_Cannot_Null" xml:space="preserve">
|
||||
<value>properties 参数不能为空</value>
|
||||
|
@ -206,6 +206,14 @@ namespace FreeSql.ClickHouse.Curd
|
||||
_updateVersionValue = Utils.GuidToBytes(Guid.NewGuid());
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.GetNoneParamaterSqlValue(_paramsSource, "uv", _table.VersionColumn, _table.VersionColumn.Attribute.MapType, _updateVersionValue));
|
||||
}
|
||||
else if (_versionColumn.Attribute.MapType == typeof(string))
|
||||
{
|
||||
_updateVersionValue = Guid.NewGuid().ToString();
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_noneParameter ? _commonUtils.GetNoneParamaterSqlValue(_paramsSource, "uv", _versionColumn, _versionColumn.Attribute.MapType, _updateVersionValue) :
|
||||
_commonUtils.QuoteWriteParamterAdapter(_versionColumn.Attribute.MapType, _commonUtils.QuoteParamterName($"p_{_paramsSource.Count}")));
|
||||
if (_noneParameter == false)
|
||||
_commonUtils.AppendParamter(_paramsSource, null, _versionColumn, _versionColumn.Attribute.MapType, _updateVersionValue);
|
||||
}
|
||||
else
|
||||
sb.Append(", ").Append(vcname).Append(" = ").Append(_commonUtils.IsNull(vcname, 0)).Append(" + 1");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user