Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
Efcore.Pg
提交
c6b84605
E
Efcore.Pg
项目概览
jobily
/
Efcore.Pg
12 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
Efcore.Pg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
c6b84605
编写于
2月 10, 2020
作者:
S
Shay Rojansky
提交者:
GitHub
2月 10, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Sugar to easily configure tsvector generated columns (#1262)
Closes #1253
上级
e6cbfd6c
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
383 addition
and
9 deletion
+383
-9
src/EFCore.PG/Extensions/MemberInfoExtensions.cs
src/EFCore.PG/Extensions/MemberInfoExtensions.cs
+0
-0
src/EFCore.PG/Extensions/NpgsqlEntityTypeBuilderExtensions.cs
...EFCore.PG/Extensions/NpgsqlEntityTypeBuilderExtensions.cs
+57
-0
src/EFCore.PG/Extensions/NpgsqlPropertyBuilderExtensions.cs
src/EFCore.PG/Extensions/NpgsqlPropertyBuilderExtensions.cs
+133
-1
src/EFCore.PG/Extensions/NpgsqlPropertyExtensions.cs
src/EFCore.PG/Extensions/NpgsqlPropertyExtensions.cs
+116
-3
src/EFCore.PG/Metadata/Internal/NpgsqlAnnotationNames.cs
src/EFCore.PG/Metadata/Internal/NpgsqlAnnotationNames.cs
+2
-0
src/EFCore.PG/Migrations/Internal/NpgsqlMigrationsAnnotationProvider.cs
...Migrations/Internal/NpgsqlMigrationsAnnotationProvider.cs
+15
-5
src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
+28
-0
test/EFCore.PG.FunctionalTests/MigrationsNpgsqlTest.cs
test/EFCore.PG.FunctionalTests/MigrationsNpgsqlTest.cs
+32
-0
未找到文件。
src/
Shared
/MemberInfoExtensions.cs
→
src/
EFCore.PG/Extensions
/MemberInfoExtensions.cs
浏览文件 @
c6b84605
文件已移动
src/EFCore.PG/Extensions/NpgsqlEntityTypeBuilderExtensions.cs
浏览文件 @
c6b84605
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Linq.Expressions
;
using
System.Reflection
;
using
JetBrains.Annotations
;
using
Microsoft.EntityFrameworkCore.Infrastructure
;
using
Microsoft.EntityFrameworkCore.Metadata.Builders
;
using
Npgsql.EntityFrameworkCore.PostgreSQL.Metadata.Internal
;
using
Npgsql.EntityFrameworkCore.PostgreSQL.Utilities
;
...
...
@@ -48,6 +52,59 @@ public static class NpgsqlEntityTypeBuilderExtensions
#
endregion
xmin
#
region
Generated
tsvector
column
// Note: actual configuration for generated TsVector properties is on the property
/// <summary>
/// Configures a property on this entity to be a full-text search tsvector column over other given properties.
/// </summary>
/// <param name="entityTypeBuilder">The builder for the entity being configured.</param>
/// <param name="tsVectorPropertyExpression">
/// A lambda expression representing the property to be configured as a tsvector column
/// (<c>blog => blog.Url</c>).
/// </param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
/// <param name="includeExpression">
/// <para>
/// A lambda expression representing the property(s) to be included in the tsvector column
/// (<c>blog => blog.Url</c>).
/// </para>
/// <para>
/// If multiple properties are to be included then specify an anonymous type including the
/// properties (<c>post => new { post.Title, post.BlogId }</c>).
/// </para>
/// </param>
/// <returns>A builder to further configure the property.</returns>
public
static
EntityTypeBuilder
<
TEntity
>
HasGeneratedTsVectorProperty
<
TEntity
,
TProperty
>(
[
NotNull
]
this
EntityTypeBuilder
<
TEntity
>
entityTypeBuilder
,
[
NotNull
]
Expression
<
Func
<
TEntity
,
TProperty
>>
tsVectorPropertyExpression
,
[
NotNull
]
string
config
,
[
NotNull
]
Expression
<
Func
<
TEntity
,
object
>>
includeExpression
)
where
TEntity
:
class
{
Check
.
NotNull
(
entityTypeBuilder
,
nameof
(
entityTypeBuilder
));
Check
.
NotNull
(
tsVectorPropertyExpression
,
nameof
(
tsVectorPropertyExpression
));
Check
.
NotNull
(
config
,
nameof
(
config
));
Check
.
NotNull
(
includeExpression
,
nameof
(
includeExpression
));
entityTypeBuilder
.
Property
(
tsVectorPropertyExpression
).
IsGeneratedTsVector
(
config
,
includeExpression
.
GetPropertyAccessList
().
Select
(
MemberInfoExtensions
.
GetSimpleMemberName
).
ToArray
());
return
entityTypeBuilder
;
}
#
endregion
Generated
tsvector
column
#
region
Storage
parameters
/// <summary>
...
...
src/EFCore.PG/Extensions/NpgsqlPropertyBuilderExtensions.cs
浏览文件 @
c6b84605
using
System
;
using
System.Collections
;
using
System.Collections.Generic
;
using
JetBrains.Annotations
;
using
Microsoft.EntityFrameworkCore.Metadata
;
using
Microsoft.EntityFrameworkCore.Metadata.Builders
;
...
...
@@ -611,5 +612,136 @@ public static IConventionPropertyBuilder UseIdentityByDefaultColumn([NotNull] th
}
#
endregion
Identity
options
#
region
Generated
tsvector
column
// Note: tsvector properties can be configured with a generic API through the entity type builder
/// <summary>
/// Configures the property to be a full-text search tsvector column over the given properties.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
/// <param name="includedPropertyNames">An array of property names to be included in the tsvector.</param>
/// <returns>A builder to further configure the property.</returns>
public
static
PropertyBuilder
IsGeneratedTsVector
(
[
NotNull
]
this
PropertyBuilder
propertyBuilder
,
[
NotNull
]
string
config
,
[
NotNull
]
params
string
[]
includedPropertyNames
)
{
Check
.
NotNull
(
propertyBuilder
,
nameof
(
propertyBuilder
));
Check
.
NotNull
(
config
,
nameof
(
config
));
Check
.
NotEmpty
(
includedPropertyNames
,
nameof
(
includedPropertyNames
));
propertyBuilder
.
HasColumnType
(
"tsvector"
);
propertyBuilder
.
Metadata
.
SetGeneratedTsVectorConfig
(
config
);
propertyBuilder
.
Metadata
.
SetGeneratedTsVectorProperties
(
includedPropertyNames
);
return
propertyBuilder
;
}
/// <summary>
/// Configures the property to be a full-text search tsvector column over the given properties.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
/// <param name="includedPropertyNames">An array of property names to be included in the tsvector.</param>
/// <returns>A builder to further configure the property.</returns>
public
static
PropertyBuilder
<
TProperty
>
IsGeneratedTsVector
<
TProperty
>(
[
NotNull
]
this
PropertyBuilder
<
TProperty
>
propertyBuilder
,
[
NotNull
]
string
config
,
[
NotNull
]
params
string
[]
includedPropertyNames
)
=>
(
PropertyBuilder
<
TProperty
>)
IsGeneratedTsVector
((
PropertyBuilder
)
propertyBuilder
,
config
,
includedPropertyNames
);
/// <summary>
/// Configures the property to be a full-text search tsvector column over the given properties.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
/// <param name="includedPropertyNames">An array of property names to be included in the tsvector.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns>
/// The same builder instance if the configuration was applied,
/// <c>null</c> otherwise.
/// </returns>
public
static
IConventionPropertyBuilder
IsGeneratedTsVector
(
[
NotNull
]
this
IConventionPropertyBuilder
propertyBuilder
,
[
CanBeNull
]
string
config
,
[
CanBeNull
]
IReadOnlyList
<
string
>
includedPropertyNames
,
bool
fromDataAnnotation
=
false
)
{
Check
.
NotNull
(
propertyBuilder
,
nameof
(
propertyBuilder
));
if
(
propertyBuilder
.
CanSetIsGeneratedTsVector
(
config
,
includedPropertyNames
,
fromDataAnnotation
))
{
propertyBuilder
.
HasColumnType
(
"tsvector"
);
propertyBuilder
.
Metadata
.
SetGeneratedTsVectorConfig
(
config
,
fromDataAnnotation
);
propertyBuilder
.
Metadata
.
SetGeneratedTsVectorProperties
(
includedPropertyNames
,
fromDataAnnotation
);
return
propertyBuilder
;
}
return
null
;
}
/// <summary>
/// Returns a value indicating whether the property can be configured as a full-text search tsvector column.
/// </summary>
/// <param name="propertyBuilder">The builder for the property being configured.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
/// <param name="includedPropertyNames">An array of property names to be included in the tsvector.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <returns><c>true</c> if the property can be configured as a full-text search tsvector column.</returns>
public
static
bool
CanSetIsGeneratedTsVector
(
[
NotNull
]
this
IConventionPropertyBuilder
propertyBuilder
,
[
CanBeNull
]
string
config
,
[
CanBeNull
]
IReadOnlyList
<
string
>
includedPropertyNames
,
bool
fromDataAnnotation
=
false
)
{
Check
.
NotNull
(
propertyBuilder
,
nameof
(
propertyBuilder
));
return
(
fromDataAnnotation
?
ConfigurationSource
.
DataAnnotation
:
ConfigurationSource
.
Convention
)
.
Overrides
(
propertyBuilder
.
Metadata
.
GetGeneratedTsVectorConfigConfigurationSource
())
&&
(
fromDataAnnotation
?
ConfigurationSource
.
DataAnnotation
:
ConfigurationSource
.
Convention
)
.
Overrides
(
propertyBuilder
.
Metadata
.
GetGeneratedTsVectorPropertiesConfigurationSource
())
||
config
==
propertyBuilder
.
Metadata
.
GetGeneratedTsVectorConfig
()
&&
StructuralComparisons
.
StructuralEqualityComparer
.
Equals
(
includedPropertyNames
,
propertyBuilder
.
Metadata
.
GetGeneratedTsVectorProperties
());
}
#
endregion
Generated
tsvector
column
}
}
src/EFCore.PG/Extensions/NpgsqlPropertyExtensions.cs
浏览文件 @
c6b84605
using
System
;
using
System.Globalization
;
using
System.Text
;
using
System.Collections.Generic
;
using
JetBrains.Annotations
;
using
Microsoft.EntityFrameworkCore.Diagnostics
;
using
Microsoft.EntityFrameworkCore.Infrastructure
;
using
Microsoft.EntityFrameworkCore.Metadata
;
using
Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
;
...
...
@@ -477,5 +475,120 @@ public static void RemoveIdentityOptions([NotNull] this IConventionProperty prop
=>
property
.
RemoveAnnotation
(
NpgsqlAnnotationNames
.
IdentityOptions
);
#
endregion
Identity
sequence
options
#
region
Generated
tsvector
column
/// <summary>
/// Returns the text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </returns>
public
static
string
GetGeneratedTsVectorConfig
([
NotNull
]
this
IProperty
property
)
=>
(
string
)
property
[
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
];
/// <summary>
/// Sets the text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
public
static
void
SetGeneratedTsVectorConfig
([
NotNull
]
this
IMutableProperty
property
,
[
CanBeNull
]
string
config
)
=>
property
.
SetOrRemoveAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
,
config
);
/// <summary>
/// Returns the text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <param name="config">
/// <para>
/// The text search configuration for this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </para>
/// <para>
/// See https://www.postgresql.org/docs/current/textsearch-controls.html for more information.
/// </para>
/// </param>
public
static
void
SetGeneratedTsVectorConfig
(
[
NotNull
]
this
IConventionProperty
property
,
[
NotNull
]
string
config
,
bool
fromDataAnnotation
=
false
)
=>
property
.
SetOrRemoveAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
,
config
,
fromDataAnnotation
);
/// <summary>
/// Returns the <see cref="ConfigurationSource" /> for the text search configuration for the generated tsvector
/// property.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The configuration source for the text search configuration for the generated tsvector property.</returns>
public
static
ConfigurationSource
?
GetGeneratedTsVectorConfigConfigurationSource
([
NotNull
]
this
IConventionProperty
property
)
=>
property
.
FindAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
)?.
GetConfigurationSource
();
/// <summary>
/// Returns the properties included in this generated tsvector property, or <c>null</c> if this is not a
/// generated tsvector property.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The included property names, or <c>null</c> if this is not a Generated tsvector column.</returns>
public
static
IReadOnlyList
<
string
>
GetGeneratedTsVectorProperties
([
NotNull
]
this
IProperty
property
)
=>
(
string
[])
property
[
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
];
/// <summary>
/// Sets the properties included in this generated tsvector property, or <c>null</c> to make this a regular,
/// non-generated property.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="properties">The included property names.</param>
public
static
void
SetGeneratedTsVectorProperties
(
[
NotNull
]
this
IMutableProperty
property
,
[
CanBeNull
]
IReadOnlyList
<
string
>
properties
)
=>
property
.
SetOrRemoveAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
,
properties
);
/// <summary>
/// Sets properties included in this generated tsvector property, or <c>null</c> to make this a regular,
/// non-generated property.
/// </summary>
/// <param name="property">The property.</param>
/// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>
/// <param name="properties">The included property names.</param>
public
static
void
SetGeneratedTsVectorProperties
(
[
NotNull
]
this
IConventionProperty
property
,
[
CanBeNull
]
IReadOnlyList
<
string
>
properties
,
bool
fromDataAnnotation
=
false
)
=>
property
.
SetOrRemoveAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
,
properties
,
fromDataAnnotation
);
/// <summary>
/// Returns the <see cref="ConfigurationSource" /> for the properties included in the generated tsvector property.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The configuration source for the properties included in the generated tsvector property.</returns>
public
static
ConfigurationSource
?
GetGeneratedTsVectorPropertiesConfigurationSource
([
NotNull
]
this
IConventionProperty
property
)
=>
property
.
FindAnnotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
)?.
GetConfigurationSource
();
#
endregion
Generated
tsvector
column
}
}
src/EFCore.PG/Metadata/Internal/NpgsqlAnnotationNames.cs
浏览文件 @
c6b84605
...
...
@@ -24,6 +24,8 @@ public static class NpgsqlAnnotationNames
public
const
string
StorageParameterPrefix
=
Prefix
+
"StorageParameter:"
;
public
const
string
UnloggedTable
=
Prefix
+
"UnloggedTable"
;
public
const
string
IdentityOptions
=
Prefix
+
"IdentitySequenceOptions"
;
public
const
string
GeneratedTsVectorProperties
=
Prefix
+
"GeneratedTsVectorProperties"
;
public
const
string
GeneratedTsVectorConfig
=
Prefix
+
"GeneratedTsVectorConfig"
;
// Database model annotations
...
...
src/EFCore.PG/Migrations/Internal/NpgsqlMigrationsAnnotationProvider.cs
浏览文件 @
c6b84605
...
...
@@ -45,6 +45,18 @@ public override IEnumerable<IAnnotation> For(IProperty property)
}
}
}
if
(
property
.
GetGeneratedTsVectorConfig
()
is
string
tsVectorConfig
)
yield
return
new
Annotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
,
tsVectorConfig
);
if
(
property
.
GetGeneratedTsVectorProperties
()
is
IReadOnlyList
<
string
>
tsVectorProperties
)
{
yield
return
new
Annotation
(
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
,
tsVectorProperties
.
Select
(
p
=>
property
.
DeclaringEntityType
.
FindProperty
(
p
).
GetColumnName
())
.
ToArray
());
}
}
public
override
IEnumerable
<
IAnnotation
>
For
(
IIndex
index
)
...
...
@@ -61,13 +73,11 @@ public override IEnumerable<IAnnotation> For(IIndex index)
yield
return
new
Annotation
(
NpgsqlAnnotationNames
.
IndexNullSortOrder
,
nullSortOrder
);
if
(
index
.
GetIncludeProperties
()
is
IReadOnlyList
<
string
>
includeProperties
)
{
var
includeColumns
=
includeProperties
.
Select
(
p
=>
index
.
DeclaringEntityType
.
FindProperty
(
p
).
GetColumnName
())
.
ToArray
();
yield
return
new
Annotation
(
NpgsqlAnnotationNames
.
IndexInclude
,
includeColumns
);
includeProperties
.
Select
(
p
=>
index
.
DeclaringEntityType
.
FindProperty
(
p
).
GetColumnName
())
.
ToArray
());
}
var
isCreatedConcurrently
=
index
.
IsCreatedConcurrently
();
...
...
src/EFCore.PG/Migrations/NpgsqlMigrationsSqlGenerator.cs
浏览文件 @
c6b84605
...
...
@@ -1159,6 +1159,34 @@ protected override void Generate(CreateSequenceOperation operation, IModel model
}
}
if
(
operation
[
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
]
is
string
tsVectorConfig
)
{
var
tsVectorIncludedColumns
=
operation
[
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
]
as
string
[];
if
(
tsVectorIncludedColumns
==
null
)
throw
new
InvalidOperationException
(
$"
{
nameof
(
NpgsqlAnnotationNames
.
GeneratedTsVectorConfig
)}
is present in a migration but "
+
$"
{
nameof
(
NpgsqlAnnotationNames
.
GeneratedTsVectorProperties
)}
is absent or empty"
);
var
stringTypeMapping
=
Dependencies
.
TypeMappingSource
.
GetMapping
(
typeof
(
string
));
operation
.
ComputedColumnSql
=
new
StringBuilder
()
.
Append
(
"to_tsvector("
)
.
Append
(
stringTypeMapping
.
GenerateSqlLiteral
(
tsVectorConfig
))
.
Append
(
", "
)
.
Append
(
string
.
Join
(
" || ' ' || "
,
tsVectorIncludedColumns
.
Select
(
GetTsVectorColumnExpression
)))
.
Append
(
")"
)
.
ToString
();
string
GetTsVectorColumnExpression
(
string
includedColumn
)
{
var
delimitedColumnName
=
Dependencies
.
SqlGenerationHelper
.
DelimitIdentifier
(
includedColumn
);
var
property
=
FindProperty
(
model
,
schema
,
table
,
includedColumn
);
return
property
?.
IsColumnNullable
()
==
true
?
$"coalesce(
{
delimitedColumnName
}
, '')"
:
delimitedColumnName
;
}
}
base
.
ColumnDefinition
(
schema
,
table
,
...
...
test/EFCore.PG.FunctionalTests/MigrationsNpgsqlTest.cs
浏览文件 @
c6b84605
...
...
@@ -10,6 +10,7 @@
using
Npgsql.EntityFrameworkCore.PostgreSQL.Metadata.Internal
;
using
Npgsql.EntityFrameworkCore.PostgreSQL.Scaffolding.Internal
;
using
Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities
;
using
NpgsqlTypes
;
using
Xunit
;
using
Xunit.Abstractions
;
...
...
@@ -759,6 +760,37 @@ public virtual async Task Add_column_with_huge_varchar()
@"ALTER TABLE ""People"" ADD ""Name"" text NULL;"
);
}
[
Fact
]
public
virtual
async
Task
Add_column_generated_tsvector
()
{
if
(
TestEnvironment
.
PostgresVersion
.
IsUnder
(
12
))
{
await
Assert
.
ThrowsAsync
<
NotSupportedException
>(()
=>
base
.
Add_column_with_computedSql
());
return
;
}
await
Test
(
builder
=>
builder
.
Entity
(
"People"
,
e
=>
{
e
.
Property
<
string
>(
"Title"
).
IsRequired
();
e
.
Property
<
string
>(
"Description"
);
}),
builder
=>
{
},
builder
=>
builder
.
Entity
(
"People"
).
Property
<
NpgsqlTsVector
>(
"TsVector"
)
.
IsGeneratedTsVector
(
"english"
,
"Title"
,
"Description"
),
model
=>
{
var
table
=
Assert
.
Single
(
model
.
Tables
);
var
column
=
Assert
.
Single
(
table
.
Columns
,
c
=>
c
.
Name
==
"TsVector"
);
Assert
.
Equal
(
"tsvector"
,
column
.
StoreType
);
Assert
.
Equal
(
@"to_tsvector('english'::regconfig, ((""Title"" || ' '::text) || COALESCE(""Description"", ''::text)))"
,
column
.
ComputedColumnSql
);
});
AssertSql
(
@"ALTER TABLE ""People"" ADD ""TsVector"" tsvector GENERATED ALWAYS AS (to_tsvector('english', ""Title"" || ' ' || coalesce(""Description"", ''))) STORED;"
);
}
public
override
async
Task
Alter_column_change_type
()
{
await
base
.
Alter_column_change_type
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录