问题描述
尝试初始化SQLite-NET数据库时,我不断收到以下错误消息:
无法创建没有列的表(“ PersonModel”是否具有公共属性?)
我有一个const LectureItem = props => {
let l = props.lecture;
// let bookLeacture=props.bookLeacture
return (
<>
<Container>
<Row>
<Col>
<Alert variant="primary">
<Row>
{l.booked === false && (
<Col>
<Button
onClick={this.bookLeacture(l.lectureId)}
variant="success"
block
>
Book Now
</Button>
</Col>
)}
</Row>
</Alert>
</Col>
</Row>
</Container>
</>
);
};
class AvailableCourses extends React.Component {
bookLeacture = id => {
API.bookLeacture(id)
.then(res => {
console.log(res);
this.setState({ lectures: res,loading: null,serverErr: null });
})
.catch(err => {
this.setState({ serverErr: true,loading: null });
});
};
constructor(props) {
super(props);
this.state = { lectures: [] };
}
render() {
return (
<>
<Container fluid>
<Row className="justify-content-md-center below-nav">
<h3>Available Courses: </h3>
</Row>
{this.state.lectures.map(e => {
return <LectureItem lecture={e} bookLeacture={this.bookLeacture} />;
})}
</Container>
</>
);
}
}
export default AvailableCourses;
类,我希望它是不可变的,但是sqlite告诉我PersonModel
必须是可变的,例如每个属性都必须使用PersonModel
。
如何继续使用具有不变属性的SQLite-NET?
public set;
解决方法
说明
发生该错误是因为SQLite-NET使用Reflection初始化从数据库中检索的对象,而Reflection需要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
}
初始化每个属性。
答案
我们可以利用Init-Only Setters的新功能C# 9.0。
仅初始化设置器使我们可以定义可以在初始化期间设置且不能更改的属性。换句话说,仅初始化设置器使我们可以创建不可变对象,并且它们允许反射创建不可变对象!
我在博客文章https://codetraveler.io/2020/11/11/using-immutable-objects-with-sqlite-net/
中更深入地介绍了此主题。代码
删除public set;
上的构造函数(反射需要无参数的构造函数),并为每个属性实现仅初始化设置器:
Person
,
另一种选择是创建一个执行所有SQLite交互的PersonDto
类:
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
类封装DTO对象:
class Person
{
private PersonDto _dto;
public Person(PersonDto dto)
{
this._dto = dto;
}
public string FirstName => _dto.FirstName;
public string LastName => _dto.LastName;
}