public class Order
{
public int Id {get;set;}
[DisplayName("User")]
public long UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public decimal Amount { get; set; }
}
使用IEnumurable
public class User
{
public int Id{get;set;}
public virtual IEnumerable<Order> Orders { get; set; }
}
public User GetWithOrders()
{
var myUser=UserRepository.GetByEmail("email@email.com");
myUser.Orders=OrderRepository.GetByUserId(myUser.Id);
return myUser;
}
使用ICollection
public class User
{
public int Id{get;set;}
public virtual ICollection<Order> Orders { get; set; }
}
public User GetWithOrders()
{
var myUser=UserRepository.GetByEmail("email@email.com");
return myUser;
}
我没有使用IEnumerable
延迟加载导航属性。因此,我必须使用另一个查询来获取此用户的订单。
我有ICollection
导航。所以我可以接到用户的订单。这看起来很酷。但是,我可以在Controller中向用户添加新订单,而无需使用服务或存储库。
它在控制器级别上操纵数据。这是反模式吗?
答案 0 :(得分:2)
但是[with
ICollection
]我可以在Controller中添加新订单,而无需使用服务或存储库。
你的意思是你可以这样做(假设有一个用于向用户添加订单的视图模型以及某个地方的SaveChanges()
):
public class UserController
{
public ActionResult AddUserOrder(AddUserOrderModel addOrder)
{
User user = User.GetByEmail(addOrder.UserEmail);
user.Orders.Add(addOrder.Order);
User.SaveChanges();
}
}
尤其是您可以执行user.Orders.Add(...)
,这就是从服务或存储库层公开实体类型的副作用。
如果您想避免这种情况,您必须定义并公开包含您要公开的成员的业务对象:
public class UserBLL
{
public int Id { get; private set; }
public IEnumerable<Order> Orders { get { return _orders.AsEnumerable(); } }
private IEnumerable<Order> _orders;
public UserBLL(User user)
{
Id = user.Id;
_orders = user.Orders;
}
public void AddOrder(Order order)
{
_orders.Add(order);
}
}
答案 1 :(得分:1)
这里不是一个真正的选择。 EF需要ICollection
来控制其中某些方面,例如绑定查询结果和延迟加载。通过使用IEnumerable
,您实际上已经关闭了所有这些功能,但随之而来的是EF对您的底层结构的理解。生成迁移时,EF不会为M2M关系,相关表上的外键等生成任何必需的基础连接表。
长短,请使用ICollection
。虽然您可以通过简单地将它们添加到相关实体sans-DAL上的集合中来添加项目,但它们仍然无法保存而无法访问上下文。如果您已正确设置DAL,则只能通过DAL本身使用,因此您仍需将实体传回DAL管道以使这些更改永久化。换句话说,不要担心。