IntelliJ имеет довольно продвинутые проверки кода (сравнимые, но отличающиеся от FindBugs).
Хотя я серьезно скучаю по плагину FindBugs при использовании IntelliJ (интеграция Eclipse / FindBugs довольно крутая).
Здесь - это официальный список CodeInspections, поддерживаемых IntelliJ
РЕДАКТИРОВАТЬ: Наконец, есть findbugs-плагин для IntelliJ. Это все еще немного бета, но комбинация Code Inspections и FindBugs просто великолепна!
Да, по какой-то причине Linq to SQL выполняет все удаления в последнюю очередь. И нет никакого способа изменить это.
Или, может быть, есть. Я не заглядывал в DataContext кодогенератора, чтобы посмотреть, можем ли мы что-то там переопределить.
Вы можете вызывать SubmitChanges () сколько угодно раз. Мой обходной путь, когда мне нужно удалить в первую очередь, - это отметить мои удаления, вызвать SubmitChanges (), затем выполнить вставки и обновления и снова вызвать SubmitChanges.
Вы можете обернуть все внутри TransactionScope:
var deletables =
from toDelete in db.NamedValues
where toDelete.Name == knownValue.Name
select toDelete;
using (var scope = new TransactionScope())
{
db.NamedValues.DeleteAllOnSubmit(deletables);
db.SubmitChanges();
db.NamedValues.InsertOnSubmit(knownValue);
db.SubmitChanges();
scope.Complete();
}
I have been having this same problem. I came up with a hack to work around it, which seems to work for me: I manually execute some SQL for each potentially problematic delete in the change set before calling SubmitChanges():
foreach (object o in m_Db.GetChangeSet().Deletes)
{
LibraryMember m = o as LibraryMember;
if (m != null)
{
m_Db.ExecuteCommand("DELETE FROM LibraryMembers WHERE LibraryMemberId={0}", m.LibraryMemberId);
}
}
m_Db.SubmitChanges()
Другое решение - прикрепить изменения к другому контексту данных в правильном порядке. Однако недостатком этого решения является то, что любые объекты, на которые все еще ссылается остальная часть вашего приложения, которые были из исходного контекста данных, теперь будут недействительными: (
Я пробовал небольшой вариант этого, создав второй временный контекст данных для фиксации. Но я не могу понять, как тогда привести исходный контекст данных в чистое состояние.
Это очень расстраивает: (
public void Save()
{
string connectionString = m_Db.Connection.ConnectionString;
IList<object> deletes = m_Db.GetChangeSet().Deletes;
IList<object> inserts = m_Db.GetChangeSet().Inserts;
IList<object> updates = m_Db.GetChangeSet().Updates;
m_Db.Dispose();
m_Db = new MyDataContext(connectionString);
Attach(m_Db, deletes);
m_Db.SubmitChanges();
Attach(m_Db, updates);
m_Db.SubmitChanges();
Attach(m_Db, inserts);
m_Db.SubmitChanges();
}
void Attach(DataContext context, IList<object> items)
{
foreach (object o in items)
{
context.GetTable(o.GetType()).Attach(Clone(o));
}
}
object Clone(object o)
{
object result = o.GetType().GetConstructor(Type.EmptyTypes).Invoke(null);
foreach (PropertyInfo property in o.GetType().GetProperties())
{
if (property.PropertyType.IsValueType)
{
property.SetValue(result, property.GetValue(o, null), null);
}
}
return result;
}
Вместо того, чтобы просто выбрасывать всех детей и воссоздавать их, подумайте о том, чтобы приложить немного больше усилий и сделать это в два этапа: добавьте элементы, которые еще не добавлены, и удалите те, которые добавлено ранее, но больше не желательно. Например, на сайте ThinqLinq.com у меня есть сообщения, которые можно назначать категориям. На экране редактирования я предоставляю список категорий, которые можно выбрать и отменить. Когда я получаю сообщение, содержащее список выбранных категорий, я использую следующее для удаления и обновления соответствующих записей:
Dim selectedCats() As String = CType(ValueProvider("categories").RawValue, String())
For Each catId In selectedCats.Except(From cp In currentPost.CategoryPosts _
Select id = cp.CategoryID.ToString())
'Add new categories
currentPost.CategoryPosts.Add(New CategoryPost With {.CategoryID = CInt(catId)})
Next
'Delete removed categories
dc.CategoryPosts.DeleteAllOnSubmit(From cp In currentPost.CategoryPosts _
Where Not selectedCats.Contains(cp.CategoryID.ToString))