我目前正在使用EF4中的条件映射来过滤掉其IsActive列为false的任何记录。这可以按预期工作,但在导航关系时我遇到了一个问题。
作为一个例子,我有一对多关系,其中商店可以有很多库存记录。商店可以标记为IsActive,属于它的库存记录也可以。直接查询这些表中的记录按预期工作(仅返回活动记录),但我也能够检索关联存储未处于活动状态的库存记录。这允许访问非活动存储,并且无法检测存储是否处于活动状态。
在切换到使用条件映射之前,我们使用类似于以下的查询:
Inventories.Where(i => i.IsActive && i.Store.IsActive && i.Product.IsActive && i.Product.Id == productId);
我希望我们可以简化这个查询:
Inventories.Where(i => i.Product.Id == productId);
这对我不起作用,因为我不再知道Store或Product是否处于活动状态(因为我仍然无法在IsActive上使用条件映射,同时仍然映射该列)。
在利用EF4中的条件映射时,有没有办法复制该查询?我是否被迫离开条件映射并希望所有查询都确保检查所有相关的IsActive字段?
答案 0 :(得分:1)
您可以编写表达式访问者以将这些属性添加到查询中。
示例:
public abstract class ActiveObject
{
public bool IsActive { get; set; }
protected ActiveObject()
{
this.IsActive = true;
}
}
public class Inventory : ActiveObject
{
public Product Product { get; private set; }
public Store Store { get; private set; }
public Inventory()
{
this.Store = new Store();
this.Product = new Product { Id = 10 };
}
}
public class Product : ActiveObject
{
public int Id { get; set; }
}
public class Store : ActiveObject
{
public int Id { get; set; }
}
class Program
{
static void Main()
{
Expression<Func<Inventory, bool>> expression = i => i.Product.Id == 10;
Expression<Func<Inventory, bool>> expression2 = Rewrite(expression);
}
private static Expression<Func<Inventory, bool>> Rewrite(Expression<Func<Inventory, bool>> lambdaExpression)
{
var inventory = lambdaExpression.Parameters[0];
return Expression.Lambda<Func<Inventory, bool>>(
Expression.AndAlso(
Expression.AndAlso(
Expression.Property(
inventory,
"IsActive"
),
Expression.AndAlso(
Expression.Property(
Expression.Property(
inventory,
"Store"
),
"IsActive"
),
Expression.Property(
Expression.Property(
inventory,
"Product"
),
"IsActive"
)
)
),
lambdaExpression.Body
),
inventory
);
}
}
答案 1 :(得分:0)
虽然另一个答案可能适用于某些人,但我们决定将EF EntitySet映射到视图。视图连接到适当的表并检查其相应的IsActive
字段。我们的EDMX的结果部分看起来类似于以下内容:
<EntitySet Name="Inventory" EntityType="Model.Store.Inventory" store:Type="Views" store:Schema="dbo" store:Name="Inventory">
<DefiningQuery>SELECT
[ActiveInventory].[InventoryId] AS [InventoryId],
{Other columns being selected}
FROM [dbo].[ActiveInventory] AS [ActiveInventory]</DefiningQuery>
</EntitySet>