如何在 SQLite 中使用不可变对象?
How to use Immutable Objects with SQLite?
我在尝试初始化我的 SQLite-NET 数据库时不断收到以下错误:
Cannot create a table without columns (does 'PersonModel' have public properties?)
我有一个 class PersonModel
我想保持不变,但是 SQLite 告诉我 PersonModel
必须是可变的,例如每个 属性 必须使用 public set;
.
我如何才能继续使用具有不可变属性的 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
}
说明
发生该错误是因为 SQLite-NET 使用 Reflection 来初始化它从我们的数据库中检索到的对象,而反射需要 public set;
来初始化每个 属性.
回答
我们可以利用Init-Only Setters, new in C# 9.0。
Init-Only Setters 允许我们定义可以在初始化期间设置并且不能更改的属性。换句话说,init-only setter 让我们创建不可变对象,并且它们允许反射创建不可变对象!
我在这篇博客中更深入地探讨了这个话题 post:https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite-net/
代码
删除 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
}
另一种选择是创建一个 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; }
}
然后Person
class封装DTO对象:
class Person
{
private PersonDto _dto;
public Person(PersonDto dto)
{
this._dto = dto;
}
public string FirstName => _dto.FirstName;
public string LastName => _dto.LastName;
}
我在尝试初始化我的 SQLite-NET 数据库时不断收到以下错误:
Cannot create a table without columns (does 'PersonModel' have public properties?)
我有一个 class PersonModel
我想保持不变,但是 SQLite 告诉我 PersonModel
必须是可变的,例如每个 属性 必须使用 public set;
.
我如何才能继续使用具有不可变属性的 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
}
说明
发生该错误是因为 SQLite-NET 使用 Reflection 来初始化它从我们的数据库中检索到的对象,而反射需要 public set;
来初始化每个 属性.
回答
我们可以利用Init-Only Setters, new in C# 9.0。
Init-Only Setters 允许我们定义可以在初始化期间设置并且不能更改的属性。换句话说,init-only setter 让我们创建不可变对象,并且它们允许反射创建不可变对象!
我在这篇博客中更深入地探讨了这个话题 post:https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite-net/
代码
删除 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
}
另一种选择是创建一个 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; }
}
然后Person
class封装DTO对象:
class Person
{
private PersonDto _dto;
public Person(PersonDto dto)
{
this._dto = dto;
}
public string FirstName => _dto.FirstName;
public string LastName => _dto.LastName;
}