我有一个非常规范化的数据库,我试图将两个连接表连接在一起。
我的目标是只显示用户有权限的文档。我正在使用实体框架,并为下面的表设置了几个外键:
关系(外键)
Users ---------------------------------------------
|
UserGroupMembership (UserID, GroupID)
|
|
Groups ----- -------------------------------------------------|
|
|
|---------------------------------------------------------|
|
|
XDocuments XDocumentSecurity (DocumentID, GroupID)
| |
---------------------------------------------表定义
public partial class Users : EntityObject
{
public int UserID {get;set;} //PK
public string UserDisplayName {get;set;}
public DateTime CreateDate {get;set;}
public DateTime LoginDate {get;set;}
}
public partial class Groups : EntityObject
{
public int GroupID {get;set;} //PK
public string GroupDisplayName {get;set;}
public DateTime CreateDate {get;set;}
public DateTime LoginDate {get;set;}
}
public partial class UserGroupMembership: EntityObject // JoinTable
{
public int UserID {get;set;} //PK
public int GroupID {get;set;} //PK
// Not sure if this extra columns below causes an issue
public bool CanView {get;set;}
public bool CanDelete {get;set;}
public bool CanUpdate {get;set;}
public DateTime CreateDate {get;set;}
}
public partial class XDocumentSecurity : EntityObject // JoinTable
{
public int DocumentID {get;set;} //FK
public int GroupID {get;set;} //FK
public DateTime CreateDate {get;set;} // Not sure if this extra column causes an issue
}
public partial class XDocuments : EntityObject
{
public int DocumentID {get;set;} //PK
public string URL {get;set;}
public DateTime CreateDate {get;set;}
} 我听说过许多关于Linq to EF如何以一种性能不太理想的方式更改SQL查询的故事。
下面是操作者样本,它似乎最适用于我正在做的事情。我只需获取当前用户所属的组的列表,并发布此查询的修改版本:
public void Linq50()
{
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
var commonNumbers = numbersA.Intersect(numbersB);
Console.WriteLine("Common numbers shared by both arrays:");
foreach (var n in commonNumbers)
{
Console.WriteLine(n);
}
}问题
发布于 2011-11-04 23:31:16
如果您对所有键和外键具有导航属性,则没有Intersect的替代查询如下:
var query = context.XDocuments
.Where(d => d.Groups.Any(g => g.Users.Any(u => u.UserID == givenUserId)));(“筛选至少一个具有键=givenUserId的用户的组中的所有文档”)
我不知道这是否会更好的表现。
在EF 4.1中,您可以简单地通过以下方法检查生成的SQL:
var sql = query.ToString();编辑
我对您的模型的理解如下:
有相应表格的三个实体:
public class User
{
public int UserID { get; set; }
public ICollection<Group> Groups { get; set; }
}
public class Group
{
public int GroupID { get; set; }
public ICollection<User> Users { get; set; }
public ICollection<XDocument> Documents { get; set; }
}
public class XDocument
{
public int DocumentID { get; set; }
public ICollection<Group> Groups { get; set; }
}User和Group之间还有Group和XDocument之间的多对多关系:
modelBuilder.Entity<User>()
.HasMany(u => u.Groups)
.WithMany(g => g.Users)
.Map(c =>
{
c.MapLeftKey("UserID");
c.MapRightKey("GroupID");
c.ToTable("UserGroupMembership"); // join table name, no entity
});
modelBuilder.Entity<XDocument>()
.HasMany(d => d.Groups)
.WithMany(g => g.Documents)
.Map(c =>
{
c.MapLeftKey("DocumentID");
c.MapRightKey("GroupID");
c.ToTable("XDocumentSecurity"); // join table name, no entity
});在此模型和映射中,上述查询应该是可能的。不需要直接访问连接表(实际上不能通过LINQ实体访问它们,EF在内部管理这些表)。
发布于 2011-11-04 23:35:06
您还可以使用以下两种方法查看EF 4.1生成的SQL
尽管此时,您需要为EF4.1使用LINQPadβ。
关于你的第二个问题,我相信你的问题会翻译得很好。使用LINQPad检查SQL,以下查询
var a1 = Addresses.Where(a => a.City.ToUpper().EndsWith("L")).Select(a => a.AddressID);
var a2 = Addresses.Where(a => a.City.ToUpper().StartsWith("B")).Select(a => a.AddressID);
var x1 = a1.Intersect(a2);翻译成
SELECT
[Intersect1].[AddressID] AS [C1]
FROM (SELECT
[Extent1].[AddressID] AS [AddressID]
FROM [Person].[Address] AS [Extent1]
WHERE UPPER([Extent1].[City]) LIKE N'%L'
INTERSECT
SELECT
[Extent2].[AddressID] AS [AddressID]
FROM [Person].[Address] AS [Extent2]
WHERE UPPER([Extent2].[City]) LIKE N'B%') AS [Intersect1]如果您的模型支持的话,我认为@Slauma建议使用导航特性是可行的。
不过,去找LINQPad --你不会后悔的:)
https://stackoverflow.com/questions/8016773
复制相似问题