Насколько я понимаю, когда я открываю новый Linq в класс SQL, это эквивалент нового SqlConnection объект.
Предположим, у меня есть объект с двумя методами: Delete() и SubmitChanges(). Было бы разумно с моей стороны обновить Linq в класс SQL в каждом из методов, или будет ли частная переменная, содержащая Linq в класс SQL, созданная конструктором, будет лучшим вариантом?
Чего я пытаюсь избежать, так это тайм-аута.
Обновлено:
namespace Madtastic
{
public class Comment
{
private Boolean _isDirty = false;
private Int32 _id = 0;
private Int32 _recipeID = 0;
private String _value = "";
private Madtastic.User _user = null;
public Int32 ID
{
get
{
return this._id;
}
}
public String Value
{
get
{
return this._value;
}
set
{
this._isDirty = true;
this._value = value;
}
}
public Madtastic.User Owner
{
get
{
return this._user;
}
}
public Comment()
{
}
public Comment(Int32 commentID)
{
Madtastic.DataContext mdc = new Madtastic.DataContext();
var comment = (from c in mdc.Comments
where c.CommentsID == commentID
select c).FirstOrDefault();
if (comment != null)
{
this._id = comment.CommentsID;
this._recipeID = comment.RecipesID;
this._value = comment.CommentsValue;
this._user = new User(comment.UsersID);
}
mdc.Dispose();
}
public void SubmitChanges()
{
Madtastic.DataContext mdc = new Madtastic.DataContext();
var comment = (from c in mdc.Comments
where c.CommentsID == this._id
select c).FirstOrDefault();
if (comment != null && this._isDirty)
{
comment.CommentsValue = this._value;
}
else
{
Madtastic.Entities.Comment c = new Madtastic.Entities.Comment();
c.RecipesID = this._recipeID;
c.UsersID = this._user.ID;
c.CommentsValue = this._value;
mdc.Comments.InsertOnSubmit(c);
}
mdc.SubmitChanges();
mdc.Dispose();
}
public void Delete()
{
Madtastic.DataContext mdc = new Madtastic.DataContext();
var comment = (from c in mdc.Comments
where c.CommentsID == this._id
select c).FirstOrDefault();
if (comment != null)
{
mdc.Comments.DeleteOnSubmit(comment);
mdc.SubmitChanges();
this._isDirty = false;
this._id = 0;
this._recipeID = 0;
this._value = "";
this._user = null;
}
mdc.Dispose();
}
}
}
РЕФАКТОРНЫЙ КОД (согласно спецификации Гранка):
namespace Madtastic
{
public sealed class CommentNew : IDisposable
{
private Madtastic.DataContext _mdc;
private Madtastic.Entities.Comment _comment;
private Madtastic.User _user;
public Int32 ID
{
get
{
return this._comment.CommentsID;
}
}
public String Value
{
get
{
return this._comment.CommentsValue;
}
set
{
this._comment.CommentsValue = value;
}
}
public Madtastic.User Owner
{
get
{
return this._user;
}
}
public void Comment(Int32 commentID)
{
this._mdc = new Madtastic.DataContext();
this._comment = (from c in _mdc.Comments
where c.CommentsID == commentID
select c).FirstOrDefault();
if (this._comment == null)
{
this._comment = new Madtastic.Entities.Comment();
this._mdc.Comments.InsertOnSubmit(this._comment);
}
else
{
this._user = new Madtastic.User(this._comment.User.UsersID);
}
}
public void SubmitChanges()
{
this._mdc.SubmitChanges();
}
public void Delete()
{
this._mdc.Comments.DeleteOnSubmit(this._comment);
this.SubmitChanges();
}
void IDisposable.Dispose()
{
this._mdc.Dispose();
}
}
}





Я предполагаю, что вы имеете в виду сохранение значения для класса DataContext? Лично я предпочитаю по умолчанию использовать предложение using для всего, что является IDisposable (каковыми являются классы DataContext). Создание экземпляра в конструкторе и сохранение DataContext в частной переменной сделало бы это невозможным. Итак, для меня я бы поместил создание экземпляра в методы, но, более конкретно, я бы поместил создание экземпляра в предложение using, чтобы обеспечить правильное удаление.
Зависит от того, что вы называете «классом LINQ-to-SQL», и как выглядит рассматриваемый код.
Если вы говорите об объекте DataContext, а ваш код - это класс с длительным сроком службы или сама ваша программа, я считаю, что лучше всего инициализировать его в конструкторе. На самом деле это не похоже на создание и / или открытие нового SqlConnection, на самом деле он очень умно управляет своим пулом подключений к базе данных, параллелизмом и целостностью, так что вам не нужно думать об этом, это часть радости в моем опыте работы с LINQ-to-SQL. Я никогда не видел, чтобы возникала проблема с тайм-аутом.
Вы должны знать одну вещь: очень сложно совместно использовать объекты таблиц в области DataContext, и это действительно не рекомендуется, если вы можете этого избежать. Detach () и Attach () могут быть неприятными. Поэтому, если вам нужно передать объект LINQ-to-SQL, который представляет строку в таблице в вашей базе данных SQL, вы должны попытаться спроектировать жизненный цикл объекта DataContext, чтобы охватить всю работу, которую вам нужно выполнить с любым объектом. что выходит из этого.
Кроме того, существует много накладных расходов, связанных с созданием экземпляра объекта DataContext, и много накладных расходов, которыми он управляет ... Если вы снова и снова нажимаете одни и те же таблицы, было бы лучше использовать один и тот же экземпляр DataContext , поскольку он будет управлять своим пулом соединений и в некоторых случаях кэшировать некоторые вещи для повышения эффективности. Однако рекомендуется не загружать все таблицы в вашей базе данных в ваш DataContext, а только те, которые вам нужны, и если таблицы, к которым осуществляется доступ, очень разные в очень разных обстоятельствах, вы можете рассмотреть возможность разделения их на несколько DataContexts, что даст вам некоторые параметры при инициализации каждого из них, если окружающие их обстоятельства различны.
Один из моих текущих проектов использует Linq to SQL, где мы храним текст данных как частное поле внутри объекта. По большей части это не было проблемой, позволяет в будущем издеваться, если я передаю текст данных в конструктор, и просто кажется более чистым, чем открытие нескольких контекстов данных. Подобно тому, что упомянул Джейкоб выше, мы реализуем IDisposable, чтобы убедиться, что контекст данных может быть надежно закрыт, когда объект больше не нужен.
По умолчанию SqlConnections объединяются в пул. Вы должны обновить их кучу, чтобы оправдать затраты на объединение!
DataContexts дешево создавать (после первого). Вы должны обновить их кучу, чтобы оправдать эти первые затраты на обновление!
Теперь, просмотрев образец кода, который вы отредактировали для публикации, я определенно реорганизовал бы ваш класс, чтобы воспользоваться преимуществами встроенных функций LINQ-to-SQL. (Я не буду редактировать свой предыдущий комментарий, потому что это лучший ответ на общий вопрос)
Поля вашего класса кажутся довольно прямым отображением столбцов в таблице комментариев в базе данных. Поэтому вам не нужно делать большую часть того, что вы делаете вручную в этом классе. Большую часть функциональности можно реализовать, просто имея закрытый член типа Madtastic.Entities.Comment (и просто сопоставляя свои свойства с его свойствами, если вам нужно поддерживать взаимодействие этого класса с остальной частью проекта). Затем ваш конструктор может просто инициализировать закрытый член Madtastic.DataContext и установить закрытый член Madtastic.Entities.Comment на результат LINQ-запроса на нем. Если комментарий пустой, создайте новый и вызовите InsertOnSubmit в DataContext. (но пока не имеет смысла отправлять изменения, потому что вы все равно не установили никаких значений для этого нового объекта)
В вашем SubmitChanges все, что вам нужно сделать, это вызвать SubmitChanges в DataContext. Он самостоятельно отслеживает, нужно ли обновлять данные, в противном случае он не попадет в базу данных, поэтому вам не нужен _isDirty.
В вашем Delete () все, что вам нужно сделать, это вызвать DeleteOnSubmit в DataContext.
Фактически, сделав небольшой обзор, вы можете обнаружить, что вам вообще не нужен класс Madtastic.Comment, а класс Madtastic.Entities.Comment LINQ-to-SQL может действовать непосредственно как ваш уровень доступа к данным. Похоже, что единственными практическими отличиями являются конструктор, который принимает commentID, и тот факт, что Entities.Comment имеет свойство UsersID, где ваш класс Madtastic.Comment имеет целого User. (Однако, если User также является таблицей в базе данных, а UsersID является внешним ключом для его первичного ключа, вы обнаружите, что LINQ-to-SQL создал объект User в объекте Entities.Comment, к которому вы можете получить доступ напрямую. с комм. пользователя)
Если вы обнаружите, что можете полностью исключить этот класс, это может означать, что вы можете дополнительно оптимизировать жизненный цикл своего DataContext, добавив его к методам в вашем проекте, которые используют комментарий.
Отредактировано для публикации следующего примера реорганизованного кода (извиняюсь за любые ошибки, так как я набрал его в блокноте через пару секунд, а не открывал визуальную студию, и я бы все равно не получил intellisense для вашего проекта):
namespace Madtastic
{
public class Comment
{
private Madtastic.DataContext mdc;
private Madtastic.Entities.Comment comment;
public Int32 ID
{
get
{
return comment.CommentsID;
}
}
public Madtastic.User Owner
{
get
{
return comment.User;
}
}
public Comment(Int32 commentID)
{
mdc = new Madtastic.DataContext();
comment = (from c in mdc.Comments
where c.CommentsID == commentID
select c).FirstOrDefault();
if (comment == null)
{
comment = new Madtastic.Entities.Comment();
mdc.Comments.InsertOnSubmit(comment);
}
}
public void SubmitChanges()
{
mdc.SubmitChanges();
}
public void Delete()
{
mdc.Comments.DeleteOnSubmit(comment);
SubmitChanges();
}
}
}
Вы, вероятно, также захотите реализовать IDisposable / using, как предлагали некоторые люди.
Без проблем! Мне очень нравится LINQ, и у меня, вероятно, не всегда есть на него правильный ответ, поэтому мне нравится переполнение стека для его изучения, так как я очень скоро узнаю, ошибаюсь ли я! LINQ-to-SQL настолько нов для нас, что я думаю, что многие люди, естественно, все еще смотрят на него с точки зрения ADO.NET.
Что с "использованием"? Я не понимаю :)
ключевое слово using - это способ гарантировать, что одноразовый объект будет правильно утилизирован, когда вы закончите с ним. см. эту ветку: stackoverflow.com/questions/75401/uses-of-using-in-c
Я не мог понять, где именно «использование» будет иметь значение. Взгляните на мой обновленный код и скажите, что вы думаете. Был бы очень признателен.
Ваш новый код не так хорош, как "using", потому что любые ошибки не позволят вызвать утилиту dispose в вашем контексте. Когда "using" компилируется, он оборачивает блок в эквивалент попытки ... наконец, чтобы гарантировать, что dispose вызывается для вашего объекта независимо от того, что происходит в этом блоке.
Вау просто вау! Несомненно, лучший ответ, который я когда-либо получал здесь, на SO. Я попробую это завтра как-нибудь. Здорово, бабушка! :)