我在EF4.4中有大约12个表,我需要从公共用户查找表中加载2个属性(实际上两次执行 - 一次用于CreatedUser,一次用于ModifiedUser)。
用户表有其他非空的列,我尝试删除它们(为了节省查询结果),EF抱怨必须映射它们。有没有办法绕过这个错误,因为我不打算插入到该表中 - 只是将它用于选择。
由于FKs,它已经是一个参考属性了。如果我要将其更改为自定义视图,那么我必须手动将所有这12个重做到视图并将它们链接到此表 - 这不是世界末日,但试图避免它:)
答案 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个属性是Name
和Email
(或类似的东西),而不加载Password
,Address
等的其他值别的就在那里。我接近了吗?
我也不知道你是否使用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.
之上实现额外的缓存之前需要对它们进行检查。所有这一切,让我提出另一个可能对你有用的建议。如果您只想一次获取多个对象的UserName
和Email
,并且当时没有对对象执行任何其他操作(例如,输出对象列表) 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的对象缓存机制(至少我不要以为它会。)
另一方面,如果您对对象做了多件事,或者一次只从一个或两个(或相对较少的)对象获取相关的UserName
和Email
,我会建议依赖导航属性,也许做类似于我之前演示的内容。
我希望这对你有所帮助。如果是这样,请不要忘记投票并接受答案。谢谢;)