各位好,小弟最近在學net core mvc 搭配 entity framework core
如下有2個model 當我使用Query01()時是沒問題的
但如果想得到一個跨表單所組成的表單結果 如Query02
執行結果是跟Query01()一樣 得到所有Subjects欄位,但沒有users.UserName欄位
想請問一下如果想得到跨表單所組成的表單結果,是還要再新增一個對應model嗎?
還是有其他方法可以達成? 謝謝
Subject model:
public class Subject
{
public int Id { get; set; }
public string SubjectName { get; set; }
public int TeacherID { get; set; }
public int MaxPeople { get; set; }
}
User model:
public class User
{
public int Id { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public string UserName { get; set; }
}
public List<Subject> Query01()
{
List<Subject> result = null;
using(_DbContext){
//var query = _DbContext.Subjects;
var query = _DbContext.Subjects.FromSqlRaw("select * from subjects");
result = query.ToList();
}
return result;
}
public List<Subject> Query02()
{
List<Subject> result = null;
using(_DbContext){
var query = _DbContext.Subjects
.FromSqlRaw("select subjects.*, users.UserName from subjects left join users on subjects.TeacherID = users.Id");
result = query.ToList();
}
return result;
}
使用 導覽屬性
配合 Include
是比較正規的作法
輸出時視情況建立對應的 ViewModel
怕麻煩可以建立一個欄位多一點的 ViewModel 共用
我自己習慣以欄位的重要性區分
例如,給一般使用者看的 ViewModel,欄位就不會包含管理者才能看的資訊,這樣比較不會不小心讓資料外流
Model 部分
public class Subject
{
public int Id { get; set; }
public string SubjectName { get; set; }
public int TeacherID { get; set; }
public int MaxPeople { get; set; }
//新增 User 導覽屬性
public virtual User User { get; set; }
}
DbContext 部分
public class xxxDbContext : DbContext
{
public xxxDbContext(DbContextOptions<CoreDbContext> options)
: base(options)
{
}
public DbSet<Subject> Subjects { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Subject>(entity =>
{
//設定主索引
entity.HasKey(p => p.Id);
//設定關聯性
entity.HasOne(p => p.User).WithMany()
.HasForeignKey(p => p.TeacherID);
});
}
}
ViewModel 部分
public class SubjectViewModel
{
public int Id { get; set; }
public string SubjectName { get; set; }
public int TeacherID { get; set; }
public int MaxPeople { get; set; }
//新增使用者名稱
public string UserName { get; set; }
}
主程式
public List<SubjectViewModel> Query02()
{
var result = _DbContext.Subjects.Include(it => it.User).ToList();
return result.Select(it => new SubjectViewModel
{
Id = it.Id,
SubjectName = it.SubjectName,
MaxPeople = it.MaxPeople,
TeacherID = it.TeacherID,
UserName = it.User?.UserName
}).ToList();
}
如果不想用 Include 和 ViewModel 可以用純 LINQ
寫法
public object Query02()
{
var query = from a in _DbContext.Subjects
join b in _DbContext.Users on a.TeacherID equals b.Id
select new
{
a.Id,
a.SubjectName,
a.MaxPeople,
a.TeacherID,
b.UserName
};
return query.ToList();
}
EF 不建議直接寫 SQL,因為 Mapping 的限制很多,使用上會覺得綁手綁腳的
如果喜歡自己下 SQL,我會建議使用 Dapper,會比 EF 靈活很多
我沒這樣用過,但就我EF使用經驗,你應該需要使用Include,Include user這張表試試看,可能可以解決你的問題。
編輯一下,你用EF你的Model就要有關聯,你應該先建立關聯,跟著官方文章做應該就可以
https://docs.microsoft.com/zh-tw/ef/core/modeling/relationships?tabs=fluent-api