EF Core – Owned Entity Types & Complex Types
前言
EF Core 8.0 推出了 Complex Types,这篇要来介绍一下。
由于它和 Owned Entity Types 傻傻分不清楚,加上我之前也没有写过 Owned Entity Types 的文章,所以这篇就一起介绍呗。
Owned Entity Types
Owned Entity Types 本质上任然属于一种 Entity Types,只是它有一些潜规则,所以变得和普通 Entity Type 有所区别。
Owned Entity Types 在 Domain-driven design (领域驱动设计) 里被视作为 Aggregate 的实现。很遗憾,我对 DDD 一窍不通,无法用 DDD 视角去解释它。
Compare with one-to-one relationship
我们拿 one-to-one relationship 来做对比,这样就可以看出 Owned Entity Types 的特色了。
首先,做两个 Entity -- Order 和 OrderCustomerInfo
public class Order
{
public int Id { get; set; }
public OrderCustomerInfo CustomerInfo { get; set; } = null!;
public decimal Amount { get; set; }
} public class OrderCustomerInfo
{
public int Id { get; set; }
public Order Order { get; set; } = null!;
public string Name { get; set; } = "";
public string Phone { get; set; } = "";
}
它们是一对一关系
public class ApplicationDbContext() : DbContext()
{
public DbSet<Order> Orders => Set<Order>();
public DbSet<OrderCustomerInfo> OrderCustomerInfos => Set<OrderCustomerInfo>(); protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.HasOne(e => e.CustomerInfo).WithOne(e => e.Order).HasForeignKey<OrderCustomerInfo>(e => e.Id);
}); modelBuilder.Entity<OrderCustomerInfo>(
builder =>
{
builder.ToTable("OrderCustomerInfo");
builder.Property(e => e.Name).HasMaxLength(256);
builder.Property(e => e.Phone).HasMaxLength(256);
});
}
}
接着 insert 和 query
using var db = new ApplicationDbContext(); // insert order with customer info
db.Orders.Add(new()
{
Amount = 100,
CustomerInfo = new()
{
Name = "Derrick",
Phone = "+60 16-773 7062",
},
});
db.SaveChanges(); // query
var order = db.Orders
.Include(e => e.CustomerInfo)
.First(); Console.WriteLine(order.CustomerInfo.Name); // "Derrick"
Owned Entity Types 的特性
对比 one-to-one,Owned Entity Types 有几个特性:
Owned Entity Types 没有 DbSet

OrderCustomerInfo 不是独立的 Entity,它属于 part of the Order Entity,所以它没有 DbSet。
这也导致了它不能直接被创建,下面这句是不成立的
db.OrderCustomerInfos.Add() // 'ApplicationDbContext' does not contain a definition for 'OrderCustomerInfos'
OrderCustomerInfo 需要依附在 Order 上才能一起被创建,像这样
db.Orders.Add(new()
{
Amount = 100,
CustomerInfo = new()
{
Name = "Derrick",
Phone = "+60 16-773 7062",
},
});自动 Include
没有 DbSet 自然也无法直接 query
db.OrderCustomerInfos.ToList() // 'ApplicationDbContext' does not contain a definition for 'OrderCustomerInfos'
要获取 OrderCustomerInfo 只能透过 Order。另外 Owned Entity Types 有一个特色 -- 它会自动被 Include 出来。

即便我们没有写 Include,Owned Entity Types 依然会被 eager loading 出来。
same Table

默认情况下,Owned Entity Types (OrderCustomerInfo) 会和它依附的 Entity Types (Order) 存放在同一个数据库 Table,还有 column name 会加上 prefix,这就像使用了 Table Splitting 的那样。
Id become shadow property

Owned Entity Types 任然是 Entity Types,它依然有 primary key 的概念,只是它改成了 Shadow Property,在 class 会看不见 Id。
Config Owned Entity Types



替换成这样
modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.OwnsOne(e => e.CustomerInfo, builder =>
{
builder.Property(e => e.Name).HasMaxLength(256);
builder.Property(e => e.Phone).HasMaxLength(256);
});
});
效果
// query
var order = db.Orders.First(); Console.WriteLine(order.CustomerInfo.Name); // "Derrick"
不需要 Include,它会自动 Include。
数据库 Order Table

OrderCustomerInfo 的属性被映射到 Order Table,而且 column name 加了 prefix "CustomerInfo" 这名字来自 Order.CustomerInfo 属性。
我们调 Entity Model 出来证实一下,Owned Entity Types 也是一种 Entity Types 而且它其实是有 Key 的。
using var db = new ApplicationDbContext();
var customerEntityType = db.Model.FindEntityType(typeof(OrderCustomerInfo))!; // Owned Entity Types 也是一种 Entity Types
var isOwned = customerEntityType.IsOwned(); // true,OrderCustomerInfo 是 Owned Entity Types
var property = customerEntityType.GetProperty("OrderId")!;
Console.WriteLine(property.IsShadowProperty()); // true,"OrderId" 是 Shadow Property
Console.WriteLine(property.IsKey()); // true,"OrderId" 是 Primary Key
Console.WriteLine(property.IsForeignKey()); // true,"OrderId" 是 Foreign Key var orderEntityType = db.Model.FindEntityType(typeof(Order))!;
Console.WriteLine(orderEntityType.FindNavigation("CustomerInfo")!.ForeignKey); // "OrderId", CustomerInfo 属性不是普通的 Property 而是 Navigation
Two Table
默认情况下 Owned Entity Types (OrderCustomerInfo) 会和它的 Owner (Order) 共用一个 Table。
如果我们不希望这样,则可以使用 Entity Splitting 将它们分开成两个 Table。

column name prefix 会自动被拿掉。
效果


Sharing Owned Entity Types
Owned Entity Types 最好不要共用,不顺风水。
public class Address
{
public string Street1 { get; set; } = "";
public string Street2 { get; set; } = "";
public string PostalCode { get; set; } = "";
public string Country { get; set; } = "";
} public class Order
{
public int Id { get; set; }
public Address BillingAddress { get; set; } = null!;
public Address ShippingAddress { get; set; } = null!;
public decimal Amount { get; set; }
} public class Customer
{
public int Id { get; set; }
public string Name { get; set; } = "";
public Address Address { get; set; } = null!;
}
Order 和 Customer 都使用了 Address。
试想,如果是一对一关系,上面这样做成立吗?
答案是不成立,因为一对一关系是靠 id 作为 foreign key 维持关系的,上面这样就乱了套了。
我们测试看强制设置 Owned Entity Types 出来的效果是怎样的。
public class ApplicationDbContext() : DbContext()
{
public DbSet<Order> Orders => Set<Order>();
public DbSet<Customer> Customers => Set<Customer>(); protected override void OnModelCreating(ModelBuilder modelBuilder)
{
static void BuildAction<TEntity>(OwnedNavigationBuilder<TEntity, Address> builder) where TEntity : class
{
builder.Property(e => e.Street1).HasMaxLength(256);
builder.Property(e => e.Street2).HasMaxLength(256);
builder.Property(e => e.PostalCode).HasMaxLength(256);
builder.Property(e => e.Country).HasMaxLength(256);
} modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.OwnsOne(e => e.BillingAddress, BuildAction);
builder.OwnsOne(e => e.ShippingAddress, BuildAction);
}); modelBuilder.Entity<Customer>(
builder =>
{
builder.ToTable("Customer");
builder.Property(e => e.Name).HasMaxLength(256);
builder.OwnsOne(e => e.Address, BuildAction);
});
}
}
BuildAction 是共用的。
效果


如果做 Entity Splitting 的话,就会多出 3 个 Table -- CustomerAddress,OrderBillingAddress,OrderShippingAddress。
从这个结构可以看出,它底层依然是一对一的概念,只是在上层搞了许多映射。
我们进资料看看
using var db = new ApplicationDbContext();
var address = new Address
{
Street1 = "test",
Street2 = "test",
PostalCode = "81300",
Country = "Malaysia"
};
db.Orders.Add(new()
{
Amount = 100,
ShippingAddress = address,
BillingAddress = address
});
db.SaveChanges();
注意,shippingAddress 和 billingAddress 使用了同一个 address 对象。
运行结果是报错

因为官网声明了,Owned Entity Types 实例是不可以共享的,必须一个对一个。

我觉得 EF Core 如果硬硬要做映射是可以做到的,只是他们认为这种使用方式已经脱离了 Owned Entity Types 的本意,所以才不支持它。
但是,EF Core 8.0 推出的 Complex Types 支持这种使用方式,Complex Types 和 Owned Entity Types 有几分相似下一 part 会详细讲。
Collections of owned types
Owned Entity Types 不仅仅可以映射一对一关系,一对多关系也可以映射。
但是一对多就不可能共用同一个数据库 Table 了,一定是 2 个 Table。
其它特性,比如没有 DbSet,自动 Include,不能 share instance 这些则都一样。
来个简单的示范
Entity
public class Address
{
public string Street1 { get; set; } = "";
public string Street2 { get; set; } = "";
public string PostalCode { get; set; } = "";
public string Country { get; set; } = "";
} public class Customer
{
public int Id { get; set; }
public string Name { get; set; } = "";
public List<Address> Addresses { get; set; } = [];
}
ModelBuilder
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>(
builder =>
{
builder.ToTable("Customer");
builder.Property(e => e.Name).HasMaxLength(256);
builder.OwnsMany(e => e.Addresses, builder =>
{
builder.Property(e => e.Street1).HasMaxLength(256);
builder.Property(e => e.Street2).HasMaxLength(256);
builder.Property(e => e.PostalCode).HasMaxLength(256);
builder.Property(e => e.Country).HasMaxLength(256);
});
});
}
数据库


和普通一对多的表结构是一样的。
using var db = new ApplicationDbContext();
var addressEntityType = db.Model.FindEntityType(typeof(Address))!;
addressEntityType.GetProperty("Id").IsKey(); // true
addressEntityType.GetProperty("Id").IsShadowProperty(); // true
addressEntityType.GetProperty("CustomerId").IsForeignKey(); // true
addressEntityType.GetProperty("CustomerId").IsShadowProperty(); // true
CustomerId 是 Foreign Key,Id 是 Primary Key,它们都是 Shadow Property。
如果想修改 Primary Key 和 Foreign Key 可以这样配置
builder.OwnsMany(e => e.Addresses, builder =>
{
builder.WithOwner().HasForeignKey("CustomerId2"); // rename foreign key CustomerId to CustomerId2
builder.Property<int>("Id").HasColumnName("AddressId"); // rename primary key Id to AddressId
});
How to detech Owned Entity Types modified?
相关 Issue:
Detecting if an owned entity was changed
Return true for IsModified on navigations pointing to Added or Deleted entities
How can I get a deleted owned entity from the parent entity?
我们来看一个简单的例子
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public Address Address { get; set; } = null!;
} public class Address
{
public string Line1 { get; set; } = null!;
}
Address 是 Owned Entity Type。
var product = db.Products.AsTracking().Single();
product.Address.Line1 = "new line";
var isProductChanged = db.Entry(product).State == EntityState.Modified; // false
var isAddressPropertyModified = db.Entry(product).Reference(e => e.Address).IsModified; // false
var isAddressChanged = db.Entry(product.Address).State == EntityState.Modified; // true
var isLine1PropertyModified = db.Entry(product.Address).Property(e => e.Line1).IsModified; // true
我们从 product 对象进入到 address 对象里,然后修改 line1 的值。
可以看到,从 product entry 是完全感知不到任何 modified,只有 product.address entry 才能感知到 modified。
我们换一个修改方式
await using var db = new ApplicationDbContext(); var product = db.Products.AsTracking().Single();
var oldAddress = product.Address;
var newAddress = new Address { Line1 = "new line" };
product.Address = newAddress; var isProductChanged = db.Entry(product).State == EntityState.Modified; // false
var isAddressPropertyModified = db.Entry(product).Reference(e => e.Address).IsModified; // true
var isAddressChanged = db.Entry(product.Address).State == EntityState.Modified; // false
var isLine1PropertyModified = db.Entry(product.Address).Property(e => e.Line1).IsModified; // false
var isOldAddressDeleted = db.Entry(oldAddress).State == EntityState.Deleted; // true
var isNewAddressAdded = db.Entry(oldAddress).State == EntityState.Added; // true
新旧 address 对象替换,这样操作的话属于 add and delete,同时 product entry 的 address reference 会感知到 modified (注:但是 product entry 依旧是 unchanged 哦)。
To JSON
Owned Entity Types 还有一个强项,它可以以 JSON 格式保存到数据库里,不管是 OwnsOne 还是 OwnsMany 都行。
builder.OwnsMany(e => e.Addresses, builder =>
{
builder.ToJson();
builder.Property(e => e.Street1).HasMaxLength(256);
builder.Property(e => e.Street2).HasMaxLength(256);
builder.Property(e => e.PostalCode).HasMaxLength(256);
builder.Property(e => e.Country).HasMaxLength(256);
});
加一句 ToJson() 就可以了。
测试
using var db = new ApplicationDbContext();
db.Customers.Add(new()
{
Name = "Derrick",
Addresses = [
new() { Street1 = "test1", Street2 = "test1", PostalCode = "81300", Country = "Malaysia" },
new() { Street1 = "test2", Street2 = "test2", PostalCode = "123456", Country = "Singapore" }
]
});
db.SaveChanges();
效果

厉害吧
Nested Owned Entity Types
Owned Entity Types 支持嵌套,配置的方式和上面一样,在 OwnsOne / Many 里面继续调用 OwnsOne / Many 就可以了。
这里我就不演示了。
另外,ToJson 的话,一定要在最上层调用。
目前不支持一半一半的状况,要 JSON 就得从上层到下层通通 JSON。
Limitation

目前不支持 inheritance hierarchies 继承结构,TPH、TPT、TPC 通通不支持,希望未来会支持。
Complex Types
参考:Docs – Value objects using Complex Types
EF Core 8.0 推出了 Complex Types。Complex Types 和 Owned Entity Types 外观有点像,但内在思想是不同的。
Complex Types 在 Domain-driven design (领域驱动设计) 里被视作为 Value Object 的实现。很遗憾,我对 DDD 一窍不通,无法用 DDD 视角去解释它。
Current limitations
目前 Complex Types 还不算完整,它有很多该有得功能都还没有实现,要使用它要小心哦。

不支持一对多关系。
不支持 nullable
public OrderCustomerInfo? CustomerInfo { get; set; }像上面这样 OrderCustomerInfo 将无法设置成 Complex Types,因为它是 nullable。
不支持 ToJson。
这几个都挺需要的,既然都没有
和 Owned Entity Types 的共同点和区别
共同点:
没有 DbSet,不可以直接 Add 和 Query
- 自动 Include
区别:
Complex Types 不支持一对一映射到 two table。
Complex Types 不继承 Entity Types,因为它完全没有 Primary Key 概念。
Complex Types 的实例是可以共用的。
- Complex Types 更倾向使用 record 而非 class。
Config Complex Types
和 config Owned Entity Types 大同小异。
Entity
public class Order
{
public int Id { get; set; }
public OrderCustomerInfo CustomerInfo { get; set; } = null!;
public decimal Amount { get; set; }
} public class OrderCustomerInfo
{
public string Name { get; set; } = "";
public string Phone { get; set; } = "";
}
ModelBuilder
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(
builder =>
{
builder.ToTable("Order");
builder.Property(e => e.Amount).HasPrecision(19, 2);
builder.ComplexProperty(e => e.CustomerInfo, builder =>
{
builder.Property(e => e.Name).HasMaxLength(256);
builder.Property(e => e.Phone).HasMaxLength(256);
});
});
}
效果

Entity Model
using var db = new ApplicationDbContext();
var customerInfoEntityType = db.Model.FindEntityType(typeof(OrderCustomerInfo)); // null
var orderEntityType = db.Model.FindEntityType(typeof(Order))!;
var customerInfoProperty = orderEntityType.FindProperty("CustomerInfo"); // null
var customerInfoComplexProperty = orderEntityType.FindComplexProperty("CustomerInfo");
OrderCustomerInfo 不是 Entity Types,所以 FindEntityType 是找不到的,这点和 Owned Entity Types 不同。
另外,CustomerInfo 也不是普通的 Property 也不是 Navigation,而是 ComplexProperty,要使用 FindComplexProperty 才能获取到,这点也和 Owned Entity Types 不同。
DbContext.Entry
Entity Model 不一样,那访问 Entry CurrentValue,IsModified 这些自然也不一样了。
Entity
public class Order
{
public int Id { get; set; }
public OrderCustomerInfo CustomerInfo { get; set; } = null!;
public Address ShippingAddress { get; set; } = null!;
public decimal Amount { get; set; }
}
假设 OrderCustomerInfo 是 Complex Types,ShippingAddress 是 Owned Entity Types
想访问 ShippingAddress 的 CurrentValue 通过 DbContext.Entry 就可以了。
var order = db.Orders.First();
var shippingAddressEntry = db.Entry(order.ShippingAddress);
var countryValue = shippingAddressEntry.Property(e => e.Country).CurrentValue;
想访问 CustomerInfo 的 CurrentValue 通过 DbContext.Entry 会报错。
var customerInfoEntry = db.Entry(order.CustomerInfo); // error
因为 Complex Types 不是 Entity Types,它没有 Key 的概念。
正确的方式是先进入 OrderEntry 然后使用 ComplexProperty 找到 CustomerInfo 在进入它的 Property 获取 CurrentValue
var orderEntry = db.Entry(order);
var nameValue = orderEntry.ComplexProperty(e => e.CustomerInfo).Property(e => e.Name).CurrentValue
Immutable
Value Object 虽然是对象,但它通常是值类型 (Immutable)。
所以一般都是使用 struct / record 而不是 class。(虽然 EF Core 支持使用 class 而且即使不是 Immutable 它也可以 tracking 到 changes)
Entity
public class Order
{
public int Id { get; set; }
public OrderCustomerInfo CustomerInfo { get; set; } = null!;
public decimal Amount { get; set; }
} public record OrderCustomerInfo(string Name, string Phone);
Add Order
using var db = new ApplicationDbContext();
db.Orders.Add(new()
{
Amount = 100,
CustomerInfo = new("Derrick", "+60 16-773 7062")
});
db.SaveChanges();
update CustomerInfo
var order = db.Orders.First();
order.CustomerInfo = order.CustomerInfo with { Name = "New Name" };
db.SaveChanges();
个人觉得使用 record 会比使用 class 更合适。不熟悉 record 的朋友可以看这篇 C# – Record, Class, Struct
总结
我们可以把 Owned Entity Types 视为变种的 one-to-one 和 one-to-many。
它最大的好处是自动 Include,自动 Table Splitting,而且可以 ToJson,底层思想继承自 one-to-one 和 one-to-many Entity Types 也算很好理解。
目前只有一个缺陷 -- 不支持继承结构。
Complex Types 不是 one-to-one 和 one-to-many 的概念,它没有 Key,它不是 Entity Types。
它适合用在 Object Value,就是说这些属性确确实实是 Property 只是它们有关系所以被 group 在一起。
比如说,地址本来是一个 string "11, Jalan Merak 22, Taman Mutiara Rini, 81300 Johor Malaysia",我想把它做的有结构,
于是拆分成 Street1, Street2, PostalCode, State, Country,这种情况就适合使用 Complex Types 来表达。
EF Core – Owned Entity Types & Complex Types的更多相关文章
- 【EF Core】Entity Framework Core 批处理语句
在Entity Framework Core (EF Core)有许多新的功能,最令人期待的功能之一就是批处理语句.那么批处理语句是什么呢?批处理语句意味着它不会为每个插入/更新/删除语句发送单独的请 ...
- Entity Framework (EF) Core工具创建一对多和多对多的关系
一. EntirtyFramework(EF)简介 EntirtyFramework框架是一个轻量级的可扩展版本的流行实体框架数据访问技术,微软官方提供的ORM工具让开发人员节省数据库访问的代码时间 ...
- 在EF Core里面如何使用以前EntityFramework的DbContext.Database.SqlQuery<SomeModel>自定义查询
问: With Entity Framework Core removing dbData.Database.SqlQuery<SomeModel> I can't find a solu ...
- ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 配置 Entity Framework Core - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 Entity Fram ...
- .NET 5/.NET Core使用EF Core 5连接MySQL数据库写入/读取数据示例教程
本文首发于<.NET 5/.NET Core使用EF Core 5(Entity Framework Core)连接MySQL数据库写入/读取数据示例教程> 前言 在.NET Core/. ...
- EF Core 新特性——Owned Entity Types
Owned Entity Types 首先owned entity type是EF Core 2.0的新特性. 至于什么是owned entity types,可以先把他理解为EF Core官方支持的 ...
- EFCore Owned Entity Types,彩蛋乎?鸡肋乎?之彩蛋篇
EFCore Owned Entity Types的定义 EFCore Owned Entity Types的文档在这里:https://docs.microsoft.com/zh-cn/ef/cor ...
- EFCore Owned Entity Types,彩蛋乎?鸡肋乎?之鸡肋篇
鸡肋 鸡肋(Chicken ribs),现代汉语词语,出自<三国志·魏书·武帝纪>裴松之注引<九州春秋>曰:"夫鸡肋,弃之如可惜,食之无所得,以比汉中,知王欲还也.& ...
- Lerning Entity Framework 6 ------ Complex types
Complex types are classes that map to a subset of columns of a table.They don't contains key. They a ...
- 张高兴的 Entity Framework Core 即学即用:(一)创建第一个 EF Core 应用
写在前面 Entity Framework Core (EF Core) 是 .NET 平台流行的对象关系映射(ORM)框架.虽然 .NET 平台中 ORM 框架有很多,比如 Dapper.NHibe ...
随机推荐
- webpack4.15.1 学习笔记(六) — 代码拆分(Code Splitting)
目录 入口起点 防止重复 动态导入(dynamic imports) 代码拆分能够将代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件.代码拆分可以用于获取更小的 bundle,以 ...
- [oeasy]python0071_字符串类型_str_string_下标运算符_中括号
回忆上次内容 上次 分辨了 静态类型 语言 动态类型 语言 python 属于 对类型要求 没有那么严格的 动态类型 语言 对 初学者很友好 不过很多时候 也容易 弄不清变量类型 直接 修 ...
- C# Winform与JS交互
一.C#调用JS函数 1.JS代码 < script language = "javascript" > function Hello(msg) { alert('我是 ...
- C#:SqlSugar中时间戳(TimeStamp)的使用
1.数据库建表 CREATE TABLE dbo.Test ( tId INT IDENTITY NOT NULL , tName NVARCHAR (20) NOT NULL , tSalary D ...
- Arch Linux install i3-wm
Arch Linux install i3-wm 简介 i3-wm 是一种动态的平铺式窗口管理器,它的设计目标是提供一个快速.简洁.可定制的桌面环境,适合开发者和高级用户使用.它有以下几个特点: 它使 ...
- LLM-01 大模型 本地部署运行 ChatGLM2-6B-INT4(6GB) 简单上手 环境配置 单机单卡多卡 2070Super8GBx2 打怪升级!
搬迁说明 之前在 CSDN 上发文章,一直想着努力发一些好的文章出来!这篇文章在 2024-04-17 10:11:55 已在 CSDN 发布 写在前面 其他显卡环境也可以!但是最少要有8GB的显存, ...
- Aug. 2024 杭二训练游记
\(\text{前言}\) 我在 \(\text{Aug. 6th}\) 到 \(\text{Aug. 25th}\) 在杭州某知名中学集训,但是我亲爱的母亲却在一开始告诉我是 \(\text{Aug ...
- nacos启动失败:No DataSource set
通过docker查看nacos的日志发现nacos好端端的突然不能用了 docker logs nacos 报错后说是no datasource set,我看了我在docker里的MySQL是正常启动 ...
- excel一次性粘贴2万行数据
测试导入文件功能中,会出现需要验证导入大批量数据文件的情况,怎么样让文件快速从1行数据变成2万行数据呢,以下讲解方法: 1.如下原文件只有2行数据,第一行是标题第二行是数据 2. 选中需要复制的第二行 ...
- Jmeter函数助手31-changeCase
changeCase函数用于字符转换大小写. 字符串修改:填入需要转换的字符 更改案例模式UPPER(默认),LOWER,CAPITALIZE:不填默认UPPER,UPPER全部转换为大写,LOWER ...