使用EF从数据库中获取特定列

时间:2015-04-11 13:49:10

标签: c# entity-framework asp.net-web-api

我有这个数据库:

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.Re‌ferenceLoopHandling = 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",}

但我不想向用户发送有关密码等朋友收藏的机密信息! 我想我可以通过在我的控制器中添加此代码来解决这个问题:

if (user.password.Equals(password))
{
    me = user;
    //adding this code :
    foreach (User friend in me.friends)
    {
        friend.password = null;
        //friend.email= null;
    }
}

但我正在寻找最重要的方法! 我希望有一种方法可以阻止EF从数据库中获取一些列。

4 个答案:

答案 0 :(得分:2)

虽然你也可以使用匿名对象,但是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();

答案 1 :(得分:1)

您可以为不包含password属性的User创建新的视图类,假设它被称为UserView类。

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>();

希望这有帮助!

答案 2 :(得分:1)

如果您想为用户的朋友指定选择内容,您只需添加:

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();

答案 3 :(得分:0)

感谢您的回复,但我找到了更好的解决方案,Martin Shishkov和erkaner的答案并没有解决我的问题,因为他们只是阻止EF获取用户密码而不是朋友集合中的密码。 我在我的数据库中创建了一个名为UserViews的视图,其中包含用户的公共信息(在这种情况下,UserViews不包含密码属性),我创建了一个名为UserView的模型,它也具有公共属性,而且我已经改变了用户模型中的好友集合,如下所示:

public virtual ICollection<UserView> friends{ get; set; }

它的效果就像我期待的那样!