Linq:为什么这种方法似乎不起作用?标准方法应该是什么?

时间:2009-12-29 14:51:36

标签: c# linq-to-sql crud

为什么这种方法似乎不起作用?标准方法应该是什么?

[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);

它也不起作用。

4 个答案:

答案 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)。