Можно ли убедить DataContext рассматривать столбец как всегда грязный?

Я просто использовал бы , Объединение

В Вашем втором запросе добавляет, что дополнительный столбец называет и добавляет '' во всех соответствующих местоположениях в других запросах

Пример

//reverse order to get the column names
select top 10 personId, '' from Telephone//No Column name assigned 
Union 
select top 10 personId, loanId from loan

8
задан Marc Gravell 13 October 2009 в 15:29
поделиться

5 ответов

На основании ответа KristoferA у меня получилось что-то вроде ниже; это зло и хрупкость (часто бывает рефлексия), но, возможно, пока этого хватит. Другой стороной битвы является изменение поведения триггеров:

partial class MyDataContext // or a base-class
{
    public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
    {
        this.MakeUpdatesDirty("UpdatedBy", "Updated_By");
        base.SubmitChanges(failureMode);
    }
}
public static class DataContextExtensions
{
    public static void MakeUpdatesDirty(
        this DataContext dataContext,
        params string[] members)
    {
        if (dataContext == null) throw new ArgumentNullException("dataContext");
        if (members == null) throw new ArgumentNullException("members");
        if (members.Length == 0) return; // nothing to do
        foreach (object instance in dataContext.GetChangeSet().Updates)
        {
            MakeDirty(dataContext, instance, members);
        }
    }
    public static void MakeDirty(
        this DataContext dataContext, object instance ,
        params string[] members)
    {
        if (dataContext == null) throw new ArgumentNullException("dataContext");
        if (instance == null) throw new ArgumentNullException("instance");
        if (members == null) throw new ArgumentNullException("members");
        if (members.Length == 0) return; // nothing to do
        const BindingFlags AllInstance = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        object commonDataServices = typeof(DataContext)
            .GetField("services", AllInstance)
            .GetValue(dataContext);
        object changeTracker = commonDataServices.GetType()
            .GetProperty("ChangeTracker", AllInstance)
            .GetValue(commonDataServices, null);
        object trackedObject = changeTracker.GetType()
            .GetMethod("GetTrackedObject", AllInstance)
            .Invoke(changeTracker, new object[] { instance });
        var memberCache = trackedObject.GetType()
            .GetField("dirtyMemberCache", AllInstance)
            .GetValue(trackedObject) as BitArray;

        var entityType = instance.GetType();
        var metaType = dataContext.Mapping.GetMetaType(entityType);
        for(int i = 0 ; i < members.Length ; i++) {
            var member = entityType.GetMember(members[i], AllInstance);
            if(member != null && member.Length == 1) {
                var metaMember = metaType.GetDataMember(member[0]);
                if (metaMember != null)
                {
                    memberCache.Set(metaMember.Ordinal, true);
                }
            }
        }
    }
}
8
ответ дан 5 December 2019 в 15:24
поделиться

К сожалению, я думаю, вам придется использовать новый DataContext

1
ответ дан 5 December 2019 в 15:24
поделиться

Подробности по адресу: http://blog.benhall.me.uk/2008/01/custom-insert-logic-with-linq-to-sql.html

Вы можете изменить поведение обновления по умолчанию. Есть два способа сделать это

Самый простой - создать хранимую процедуру (если вы не можете сделать это в своей базе данных, второй метод должен работать), которая принимает параметры вашего объекта клиента и обновляет таблицу:

  1. Создайте хранимую процедуру, у которой есть параметр для каждого свойства клиентов, которое необходимо обновить.
  2. Импортируйте эту хранимую процедуру в свой файл Linq To SQL DBML.
  3. Теперь вы можете щелкнуть правой кнопкой мыши объект клиента и выбрать «Настроить поведение».
  4. Выберите свой класс «Клиенты» в раскрывающемся списке «Класс» и «Обновить» в раскрывающемся списке поведения.
  5. Выберите «Настроить» переключатель и выберите только что созданную хранимую процедуру.
  6. Теперь вы можете сопоставить свойства класса с хранимой процедурой.

Теперь, когда Linq to SQL пытается обновить вашу таблицу Customers, вместо этого он будет использовать вашу хранимую процедуру. Просто будьте осторожны, потому что это переопределит поведение обновления для клиентов повсюду.

Второй метод - использовать частичные методы. На самом деле я этого не пробовал, поэтому, надеюсь, это может дать вам какое-то общее направление для дальнейшего развития. В частичном классе для вашего контекста данных создайте частичный метод для обновления (это будет Update_____ с тем, что ваш класс находится в пустом месте. Я бы предложил поискать в файле конструктора вашего контекста данных, чтобы убедиться, что вы выбрали правильный )

public partial SomeDataContext
{
    partial void UpdateCustomer(Customer instance)
    {
       // this is where you'd do the update, but I'm not sure exactly how it's suppose to work, though. :(
    }
}
1
ответ дан 5 December 2019 в 15:24
поделиться

Если вы хотите пойти по пути [грязного] отражения, вы можете попробовать что-нибудь вроде:

1) Переопределить SubmitChanges
2) Просмотрите набор изменений
3) Используйте отражение, чтобы получить средство отслеживания изменений для каждого обновленного объекта (см. Какой самый чистый способ сделать объект Linq «грязным»? )
4) Сделайте столбец грязным (в классе StandardTrackedObject есть поле dirtyMemberCache)

1
ответ дан 5 December 2019 в 15:24
поделиться

The following works for me. Note though that I'm using the linq2sql provider from DevArt, but that may not matter:

MyDataContext dc = new MyDataContext();

Message msg = dc.Messages.Single(m => m.Id == 1);
Message attachingMsg = new Message();
attachingMsg.Id = msg.Id;

dc.Messages.Attach(attachingMsg);

attachingMsg.MessageSubject = msg.MessageSubject + " is now changed"; // changed
attachingMsg.MessageBody = msg.MessageBody; // not changed
dc.SubmitChanges();

This produces the following sql:

UPDATE messages SET messageSubject = :p1, messageBody = :p2 WHERE Id = :key1

So, messageBody is updated even though its value is not changed. One other change necessary for this, is that for each property (column) of my entity Message, I have set UpdatedCheck = UpdateCheck.Never, except for its ID, which is the primary key.

0
ответ дан 5 December 2019 в 15:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: