Linq2Sql: Управление DataContext - PullRequest
       12

Linq2Sql: Управление DataContext

4 голосов
/ 19 декабря 2008

В следующем коде не работает как

public void Foo()
{
   CompanyDataContext db = new CompanyDataContext();
   Client client = (select c from db.Clients ....).Single();
   Bar(client);
}

public void Bar(Client client)
{
   CompanyDataContext db = new CompanyDataContext();
   db.Client.Attach(client);
   client.SomeValue = "foo";
   db.SubmitChanges();
}

Это не работает, я получаю сообщение об ошибке. «Была предпринята попытка присоединить или добавить объект, который не является новым, возможно, был загружен из другого DataContext. Это не поддерживается.»

Как вы работаете с DataContexts во всем приложении, чтобы вам не нужно было передавать ссылку?

Что

Ответы [ 6 ]

5 голосов
/ 19 декабря 2008

Они действительно имеют в виду «Это не поддерживается». Присоединение к объекту, полученному из другого контекста данных, не реализовано.

Существует несколько способов решения проблемы, рекомендуемый способ - сериализация объектов, однако это не простой и не чистый подход.

Самый простой подход, который я нашел, заключается в использовании DataContext только для чтения для извлечения таких объектов:

        MyDataContext dataContext = new MyDataContext() 
        { 
            DeferredLoadingEnabled = false, 
            ObjectTrackingEnabled = false 
        };

Объекты, полученные из этого контекста, могут быть присоединены к другому контексту, но применяются только к некоторым сценариям.

4 голосов
/ 29 июля 2009

Инфраструктура PLINQO генерирует отсоединение для всех объектов, облегчая отсоединение и повторное присоединение объектов без получения этой ошибки.

public void Foo()
{
   CompanyDataContext db = new CompanyDataContext();
   Client client = (select c from db.Clients ....).Single();
   // makes it possible to call detach here
   client.Detach();
   Bar(client);
}

public void Bar(Client client)
{
   CompanyDataContext db = new CompanyDataContext();
   db.Client.Attach(client);
   client.SomeValue = "foo";
   db.SubmitChanges();
}

Вот статья, описывающая, как был реализован отдел. http://www.codeproject.com/KB/linq/linq-to-sql-detach.aspx

1 голос
/ 19 декабря 2008

Да. Вот как это работает.

Вы отметили этот asp.net, так что, я думаю, это веб-приложение. Может быть, вы хотите один datacontext на запрос?

http://blogs.vertigo.com/personal/keithc/Blog/archive/2007/06/28/linq-to-sql-and-the-quote-request-scoped-datacontext-quote-pattern.aspx

(П.С. В WinForms намного сложнее!)

0 голосов
/ 19 декабря 2008

Я посмотрел на это и обнаружил, что он работает нормально, пока исходный DataContext был удален.

Попробуйте обернуть DataContext с помощью () и убедитесь, что ваши изменения происходят после того, как вы присоединились ко второму DataContext? У меня это сработало ..

        public static void CreateEntity()
        {
            User user = null;
            using (DataClassesDataContext dc = new DataClassesDataContext())
            {
                user = (from u in dc.Users
                        select u).FirstOrDefault();               
            }
            UpdateObject(user);
        }

        public static void UpdateObject(User user)
        {
            using (DataClassesDataContext dc = new DataClassesDataContext())
            {
                dc.Users.Attach(user);
                user.LastName = "Test B";
                dc.SubmitChanges();
            }
        }
0 голосов
/ 19 декабря 2008

Вам необходимо обработать версию объекта.

Сущность может быть присоединена как измененная без исходного состояния, только если она объявляет участника версии или не имеет политики проверки обновлений.

Таким образом, если нет элемента отметки времени или другого механизма «управления версиями», при условии, что LINQ не сможет определить, изменились ли эти данные, - следовательно, вы видите ошибку.

Я решил эту проблему, добавив столбец отметки времени в мои таблицы, но есть и другие способы обойти это. Рик Страл написал несколько приличных статей именно об этой проблеме.

Также см. это и это для получения дополнительной информации.

0 голосов
/ 19 декабря 2008

Я создал классы доступа к данным, которые инкапсулируют всю связь с Linq2Sql. Эти классы имеют свой собственный текст данных, который они используют в своих объектах.

public class ClientDataLogic
{
    private DataContext _db = new DataContext();

    public Client GetClient(int id) 
    { 
        return _db.Clients.SingleOrDefault(c => c.Id == id); 
    }

    public void SaveClient(Client c) 
    { 
        if (ChangeSetOnlyIncludesClient(c))
            _db.SubmitChanges(); 
    }
}

Конечно, вам нужно будет создавать экземпляры этого объекта, пока вам нужны эти объекты.

Проверка того, что только правый объект был изменен, является довольно сложной задачей, вы можете создать такие методы, как

void ChangeClientValue(int clientId, int value);

но это может стать большим количеством кода.

Присоединение и отсоединение - это несколько недостающая функция в Linq2Sql, если вам нужно часто ее использовать, возможно, вам следует использовать Linq2Entities.

...