从查找表中删除模型中的非空列

时间:2013-07-03 19:59:39

标签: entity-framework entity-framework-4

我在EF4.4中有大约12个表,我需要从公共用户查找表中加载2个属性(实际上两次执行 - 一次用于CreatedUser,一次用于ModifiedUser)。

用户表有其他非空的列,我尝试删除它们(为了节省查询结果),EF抱怨必须映射它们。有没有办法绕过这个错误,因为我不打算插入到该表中 - 只是将它用于选择。

由于FKs,它已经是一个参考属性了。如果我要将其更改为自定义视图,那么我必须手动将所有这12个重做到视图并将它们链接到此表 - 这不是世界末日,但试图避免它:)

1 个答案:

答案 0 :(得分:0)

让我看看我是否正确理解这一点。听起来像你有一个用户表定义如下:

public class User
{
  //just assume that the following are all properties with {get;set;}
  public int ID
  public string Name
  public string Email
  public string Password
  public string Address
  //etc etc
}

然后你有其他表定义如下:

public class SomeObject
{
  public int ID
  public string ObjectName
  public string Category
  //etc etc
  public virtual User CreatedUser
  public virtual User ModifiedUser
}

您要加载的2个属性是NameEmail(或类似的东西),而不加载PasswordAddress等的其他值别的就在那里。我接近了吗?

我也不知道你是否使用Code-First,但这就是我现在所假设的......(主要是因为这是我最熟悉的)

听起来你想要做的就是添加这样的东西:

public class SomeObject
{
  //all the other stuff here...
  public string CreatedUserName
  public string CreatedUserEmail
  public string ModifiedUserName
  public string ModifiedUserEmail
}

但你应该添加的更像是这样:

[NotMapped]
public string CreatedUserName
{
  get { return CreatedUser.Name; }
}

这样可以使EF遍历关系以获取User记录并检索Name值。 [NotMapped]属性使得EF知道它不应该期望在CreatedUserName表上找到SomeObjects列。

这是否回答了你的问题?如果没有,请尝试解释一下您正在使用的EF的味道以及您尝试使用它的内容。 ;)

[回应OP评论的附加信息]

我会警告不要试图“缓存一个瘦弱版本的User表并以这种方式查找其他属性”。这可能是过早优化的情况。换句话说,您可能会认为通过从User表中查询和缓存UserNames和电子邮件,使其工作更顺畅,但最终可能会让您的工作变得更加困难。

我并不是说在您的情况下这是肯定的,只是在您尝试优化之前,您应该真正了解EF正在做什么以及您的程序需求是什么。要做到这一点,你应该通过一些测试,看看你的瓶颈在哪里。例如,如果与数据库的网络通信是一个昂贵的瓶颈,那么添加额外的记录缓存可能会改善这一点。另一方面,如果内存和CPU限制正在减慢速度,那么缓存将是一个坏主意。我要指出的另一件事是,如果该程序将在相对靠近数据库(在同一台机器上或在同一网络上)的服务器上运行,那么额外的数据库调用不应该是一个问题。但是,如果这是一个跨越互联网的桌面应用程序,以通过T1连接(例如)连接到互联网的单个数据库服务器,那么对数据库的调用可能会成为一个巨大的问题。同样,我并不是说在你的情况下这些情况都是正确的,只是在你决定在caching that EF already does on its own.

之上实现额外的缓存之前需要对它们进行检查。

所有这一切,让我提出另一个可能对你有用的建议。如果您只想一次获取多个对象的UserNameEmail,并且当时没有对对象执行任何其他操作(例如,输出对象列表) ASP.NET MVC索引视图),我建议使用Include在您的查询中急切加载相关的用户记录,如下所示:

var query = MyDbContext.SomeObjects.Where(x => x.Category == "Foo")
  .Include(x => x.CreatedUser)
  .Include(x => x.ModifiedUser);

...或定义仅将您想要的字段选择到匿名类中的查询,如下所示:

var query = MyDbContext.SomeObjects.Where(x => x.Category == "Foo")
  .Select(x => new {
    ObjectName = x.ObjectName,
    CreatedUserName = x.CreatedUser.Name,
    CreatedUserEmail = x.CreatedUser.Email,
    ModifiedUserName = x.ModifiedUser.Name,
    ModifiedUserEmail = x.ModifiedUser.Email 
  });

第一个选项受益于使用EF已经内置的对象缓存机制,以及执行单个select语句来获取所需的所有记录,而无需获取您不需要的不相关的用户记录。第二个选项也受益于单个select语句,它只获取您需要的东西,并通过过滤掉您不感兴趣的列来进一步减少返回的数据。但它不会受益于EF的对象缓存机制(至少我不要以为它会。)

另一方面,如果您对对象做了多件事,或者一次只从一个或两个(或相对较少的)对象获取相关的UserNameEmail,我会建议依赖导航属性,也许做类似于我之前演示的内容。

我希望这对你有所帮助。如果是这样,请不要忘记投票并接受答案。谢谢;)