我已经在dotnet核心中启动了一个带有sqlite db的项目。我想了解表之间的关系是如何工作的。
这里的上下文和表格:
public class HallOfFameContext: DbContext
{
public HallOfFameContext(DbContextOptions<HallOfFameContext> options)
:base(options)
{ }
public DbSet<Joke> Jokes { get; set; }
public DbSet<User> Users { get; set; }
}
public class Joke
{
public int JokeId { get; set; }
public string Description { get; set; }
public User Author { get; set; }
public int Upvotes { get; set; }
public int Downvotes { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
}
如果数据库为空,我在应用程序启动时初始化数据库,如下所示:
context.Jokes.AddRange(
new Joke
{
Description = "Perlinpinping",
Author = new User
{
Name = "Claire"
},
Downvotes = 9354,
Upvotes = 0
},
new Joke
{
Description = "Random Joke",
Author = new User
{
Name = "Robouste"
},
Downvotes = 0,
Upvotes = 78954
}
);
当我检查我的数据库时,我发现系统足够聪明,可以在User
表中添加用户,并只将id放在Joke
表中。
到现在为止还挺好。现在的问题。当我检索笑话时,作者为空。
[HttpGet]
public IEnumerable<Joke> GetJokes()
{
return _context.Jokes;
}
Json结果:
{"jokeId":1,"description":"Perlinpinping","author":null,"upvotes":0,"downvotes":9354}
当我尝试使用http post请求添加一个新的笑话时,我得到了一个unique constraint
错误:
SqliteException:SQLite错误19:'UNIQUE约束失败:Users.UserId'。
这是有效负载请求:
{author: {userId: 2, name: "Robouste"}, description: "sdfsdfsd"}
行动:
[HttpPost]
public async Task<IActionResult> PostJoke([FromBody] Joke joke)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Jokes.Add(joke);
await _context.SaveChangesAsync();
return CreatedAtAction("GetJoke", new { id = joke.JokeId }, joke);
}
谁能解释我做错了什么?我认为这两个问题都与同样的原因有关,但我不明白为什么。
EF Core尚不支持您的关系的延迟加载。
所以你需要使用eager loading方法Include
你的关系:
[HttpGet]
public IEnumerable<Joke> GetJokes()
{
return _context.Jokes.Include(joke => joke.Author);
}
要解决更新问题,您应该查看有关使用disconnected entites的文档
在您的场景中,最简单的“修复”是从数据库中查找作者并在添加到上下文之前将其分配到joke
对象:
public async Task<IActionResult> PostJoke([FromBody] Joke joke)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var author = _context.Find<User>(joke.Author.UserId);
if (author != null)
{
//existing author
joke.Author = author;
}
_context.Jokes.Add(joke);
await _context.SaveChangesAsync();
return CreatedAtAction("GetJoke", new { id = joke.JokeId }, joke);
}