[英]How to use Immutable Objects with SQLite?
I keep getting the following error when trying to initialize my SQLite.NET database:尝试初始化SQLite.NET数据库时,我不断收到以下错误:
Cannot create a table without columns (does 'PersonModel' have public properties?)
无法创建没有列的表(“PersonModel”是否具有公共属性?)
I have a class PersonModel
that I want to be immutable, however SQLite is telling me that PersonModel
must be mutable, eg each property must use public set;
我有一个我想要不可变的 class
PersonModel
,但是 SQLite 告诉我PersonModel
必须是可变的,例如每个属性都必须使用public set;
. .
How can I continue using SQLite.NET with immutable properties?如何继续使用具有不可变属性的SQLite.NET ?
class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; } //Read-only Property, cannot be changed after initialization
public string LastName { get; } //Read-only Property, cannot be changed after initialization
}
That error is happening because SQLite.NET uses Reflection to initialize the objects it retrieves from our database, and Reflection requires public set;
发生该错误是因为 SQLite.NET 使用Reflection来初始化它从我们的数据库中检索的对象,而 Reflection 需要
public set;
to initialize each property.初始化每个属性。
We can take advantage of Init-Only Setters , new in C# 9.0 .我们可以利用C# 9.0中新增的Init-Only Setters 。
Init-Only Setters allow us to define properties that can be set during initialization, AND cannot be changed. Init-Only Setters 允许我们定义可以在初始化期间设置的属性,并且不能更改。 In other words init-only setters let us create immutable objects, AND they allow Reflection to create Immutable Objects!
换句话说,init-only setter 让我们创建不可变对象,并且它们允许反射创建不可变对象!
I go deeper into this topic in this blog post: https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite.net/我 go 在这篇博文中更深入地探讨了这个主题: https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite.net/
Remove the constructor on Person
(Reflection requires a parameterless constructor), and implement init-only setters for each property:删除
Person
上的构造函数(反射需要无参数构造函数),并为每个属性实现仅初始化的设置器:
class Person
{
public string FirstName { get; init; } //Read-only Property, can be set during initialization, but cannot be changed after initialization
public string LastName { get; init; } //Read-only Property, can be set during initialization, but cannot be changed after initialization
}
Another option is to create a PersonDto
class that does all of the SQLite interactions:另一种选择是创建一个
PersonDto
class 来执行所有 SQLite 交互:
class PersonDto
{
public PersonDto(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then the Person
class encapsulates the DTO object:然后
Person
class封装了DTO object:
class Person
{
private PersonDto _dto;
public Person(PersonDto dto)
{
this._dto = dto;
}
public string FirstName => _dto.FirstName;
public string LastName => _dto.LastName;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.