使用 EF 从数据库中获取特定列
Getting specific columns from Database with EF
我有这个数据库:
Users:
-idUser
-login
-password
-email
Relationship:
-idUser
-idFriend
在我的模型中我有这个:
public class User
{
[Key, ScaffoldColumn(false), Display(Name = "ID user")]
public int idUser { set; get; }
[StringLength(16), Display(Name = "Login")]
public string login{ set; get; }
[StringLength(16), Display(Name = "Password")]
public string password{ set; get; }
[StringLength(64), Display(Name = "Email")]
public string email{ set; get; }
public virtual ICollection<User> friends{ get; set; }
public User()
{
friends = new List<User>();
}
}
我在我的上下文中创建了这段代码,以启用自我引用多对多关系:
public DbSet<User> Users{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<User>().HasMany(m => m.friends).WithMany().Map(m =>
{
m.MapLeftKey("idUser");
m.MapRightKey("idFriend");
m.ToTable("Relationship");
});
}
这部分代码在我的控制器中响应用户请求:
[AcceptVerbs("POST")]
public User getMyInformations([FromBody] String[] data)
{
string login = data[0];
string password = data[1];
Utilisateur me = null;
User user = db.Users.Where<User>(u => u.login.Equals(login)).FirstOrDefault<User>();
if (user != null)
{
if (user.password.Equals(password))
{
me = user;
}
}
return me;
}
最后我在 Global.asax 中添加了这条指令以避免自引用循环:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
一切正常,但我有一个小问题:当我想将 Json 发送到客户端时,Json 看起来像这样:
{"friends":[{"friends":[],"idUser":2,"login":"user2","password":"1234",
"email":"user2@gmail.com"],"idUser":1,"login":"user1","password":"0000",
"email":"myEamil@gmail.com",}
但我不喜欢向用户发送关于朋友的机密信息 collection 比如密码!
我想我可以通过在我的控制器中添加这段代码来解决这个问题:
if (user.password.Equals(password))
{
me = user;
//adding this code :
foreach (User friend in me.friends)
{
friend.password = null;
//friend.email= null;
}
}
但我正在寻找最重要的方法!
我希望有一种方法可以防止 EF 从数据库中获取一些列。
您可以为不包含密码 属性 的用户创建新视图 class,假设它称为 UserView class。
UserView user = db.Users
.Where<User>(u =>u .login.Equals(login))
.Select(uw => new UserView ()
{
login = u.login,
email = u.email,
//do not include password here
}
)
.FirstOrDefault<User>();
希望对您有所帮助!
erkaner 的回答是正确的,尽管你也可以用匿名对象来做
var user = db.Users
.Where(u => u.login.Equals(login))
.Select(usr => new {
login = usr.login,
email = usr.email,
//basically include what you want
})
.FirstOrDefault();
感谢您的回复,但我为我的案例找到了更好的解决方案,Martin Shishkov 和 erkaner 的回答没有解决我的问题,因为他们只是阻止 EF 获取用户密码而不是朋友集合中的密码。
我在我的数据库中创建了一个名为 UserViews 的视图,其中包含用户的 public 信息(在这种情况下,UserViews 不包含密码属性)并且我创建了一个名为 UserView 的模型,其中包含 public 属性,我已经像这样更改了用户模型中的朋友集合:
public virtual ICollection<UserView> friends{ get; set; }
它的工作方式与我期待的一样!
好吧,如果您想为用户的朋友指定要 select 的内容,您可以简单地添加:
var user = db.Users
.Where(u => u.login.Equals(login))
.Select(usr => new {
login = usr.login,
email = usr.email,
friends = usr.Friends.Select(fr => new {
// your friend info here Ex.:
email = fr.email,
})
}).FirstOrDefault();
我有这个数据库:
Users:
-idUser
-login
-password
-email
Relationship:
-idUser
-idFriend
在我的模型中我有这个:
public class User
{
[Key, ScaffoldColumn(false), Display(Name = "ID user")]
public int idUser { set; get; }
[StringLength(16), Display(Name = "Login")]
public string login{ set; get; }
[StringLength(16), Display(Name = "Password")]
public string password{ set; get; }
[StringLength(64), Display(Name = "Email")]
public string email{ set; get; }
public virtual ICollection<User> friends{ get; set; }
public User()
{
friends = new List<User>();
}
}
我在我的上下文中创建了这段代码,以启用自我引用多对多关系:
public DbSet<User> Users{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<User>().HasMany(m => m.friends).WithMany().Map(m =>
{
m.MapLeftKey("idUser");
m.MapRightKey("idFriend");
m.ToTable("Relationship");
});
}
这部分代码在我的控制器中响应用户请求:
[AcceptVerbs("POST")]
public User getMyInformations([FromBody] String[] data)
{
string login = data[0];
string password = data[1];
Utilisateur me = null;
User user = db.Users.Where<User>(u => u.login.Equals(login)).FirstOrDefault<User>();
if (user != null)
{
if (user.password.Equals(password))
{
me = user;
}
}
return me;
}
最后我在 Global.asax 中添加了这条指令以避免自引用循环:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
一切正常,但我有一个小问题:当我想将 Json 发送到客户端时,Json 看起来像这样:
{"friends":[{"friends":[],"idUser":2,"login":"user2","password":"1234",
"email":"user2@gmail.com"],"idUser":1,"login":"user1","password":"0000",
"email":"myEamil@gmail.com",}
但我不喜欢向用户发送关于朋友的机密信息 collection 比如密码! 我想我可以通过在我的控制器中添加这段代码来解决这个问题:
if (user.password.Equals(password))
{
me = user;
//adding this code :
foreach (User friend in me.friends)
{
friend.password = null;
//friend.email= null;
}
}
但我正在寻找最重要的方法! 我希望有一种方法可以防止 EF 从数据库中获取一些列。
您可以为不包含密码 属性 的用户创建新视图 class,假设它称为 UserView class。
UserView user = db.Users
.Where<User>(u =>u .login.Equals(login))
.Select(uw => new UserView ()
{
login = u.login,
email = u.email,
//do not include password here
}
)
.FirstOrDefault<User>();
希望对您有所帮助!
erkaner 的回答是正确的,尽管你也可以用匿名对象来做
var user = db.Users
.Where(u => u.login.Equals(login))
.Select(usr => new {
login = usr.login,
email = usr.email,
//basically include what you want
})
.FirstOrDefault();
感谢您的回复,但我为我的案例找到了更好的解决方案,Martin Shishkov 和 erkaner 的回答没有解决我的问题,因为他们只是阻止 EF 获取用户密码而不是朋友集合中的密码。 我在我的数据库中创建了一个名为 UserViews 的视图,其中包含用户的 public 信息(在这种情况下,UserViews 不包含密码属性)并且我创建了一个名为 UserView 的模型,其中包含 public 属性,我已经像这样更改了用户模型中的朋友集合:
public virtual ICollection<UserView> friends{ get; set; }
它的工作方式与我期待的一样!
好吧,如果您想为用户的朋友指定要 select 的内容,您可以简单地添加:
var user = db.Users
.Where(u => u.login.Equals(login))
.Select(usr => new {
login = usr.login,
email = usr.email,
friends = usr.Friends.Select(fr => new {
// your friend info here Ex.:
email = fr.email,
})
}).FirstOrDefault();