为什么这种方法似乎不起作用?标准方法应该是什么?
[Database(Name = "Test")]
[Table(Name = "Order")]
public class Order
{
[Column(Name = "ID", IsPrimaryKey = true)]
public int ID { get; set; }
[Column(Name = "OrderDate")]
public DateTime OrderDate { get; set; }
public static Order Get(int id)
{
Order item = null;
try
{
DataContext dc = new DataContext(@"Data Source=.\sqlexpress;Initial Catalog=Test;Integrated Security=True");
var items = from order
in dc.GetTable<Order>()
where order.ID == id
select order;
item = items.FirstOrDefault<Order>();
dc.Dispose();
}
catch (Exception ex)
{
item = null;
throw ex;
}
return item;
}
public bool Delete()
{
bool success = false;
try
{
DataContext dc = new DataContext(@"Data Source=.\sqlexpress;Initial Catalog=Test;Integrated Security=True");
dc.GetTable<Order>().DeleteOnSubmit(this);
success = true;
}
catch (Exception ex)
{
success = false;
throw ex;
}
return success;
}
}
class Program
{
static void Main(string[] args)
{
Order order = Order.Get(1);
order.Delete();
Console.ReadLine();
}
}
此代码生成以下异常:
InvalidOperationException : "Cannot remove an entity that has not been attached."
我也尝试了以下内容:
DataContext dc = new DataContext(@"Data Source=(local)\sqlexpress;Initial Catalog=Relationships_Test;user=;password=;Integrated Security=True");
dc.GetTable<Order>().Attach(this);
dc.GetTable<Order>().DeleteOnSubmit(this);
它也不起作用。
答案 0 :(得分:3)
您正在DataContext
方法中创建一个新的Delete()
,该方法未“知道”您要删除的Order
对象。 (“实体未附加”)
首先将Order
对象附加到DataContext
。
修改强>
您可能需要使用item.Detach()
方法拨打Get(...)
,才能在dc.Orders.Attach(...)
方法中成功拨打Delete
。
编辑2
哦,顺便说一下:你的catch
处理程序有点无用 - 它们基本上什么都不做,因为在重新抛出异常时不会使用返回值。在调用代码中捕获异常 - 无需返回success
标记或将item
设置为null
...
编辑3
当然,正如克里斯所说,你必须致电SubmitChanges
来实际做。但是,我认为你已经这样做,只是因为你得到的例外而被问到。
答案 1 :(得分:1)
即使你将它附加到上下文中,也必须调用DataContext.SubmitChanges()来实际执行命令。
如果要调用DataContext.Dispose(),则应该从try / catch / finally子句的finally块执行此操作。您可能应该使用using statement。
,而不是手动调用它答案 2 :(得分:1)
如果您有一个在DataContext上下文中创建的对象(在本例中为Order项),则在Dispose DataContext后,该对象将成为孤立对象。
要从数据库中删除孤立对象,您需要不处理原始DataContext或以某种方式将对象附加到新的DataContext(这可能很棘手)。
解决这个问题的最简单方法是在Main方法中新建DataContext,然后在main方法的末尾Dispose DataContext(这是一个标准模式)。
答案 3 :(得分:0)
我认为让业务对象尽可能不了解持久性机制更为标准。看看LINQ to SQL设计器创建实体的方式。对象本身不知道DataContext。它们具有钩子,允许数据上下文为更改和其他钩子添加通知机制,以允许实体为其生命周期中发生的特定事件(创建,验证等)添加代码。它们也被创建为部分类实现,因此您可以根据需要添加更多代码并实现提供的部分方法挂钩。
更好,更标准的方法是使用设计器和设计器生成的类作为ORM,通过部分类实现添加更多代码。或者,您可以在生成的数据上下文之上对Repository模式(或here)进行分层,或者甚至选择其他ORM(例如nHibernate)。