В LINQtoSQL, как я могу обновить дочерние отношения путем редактирования родительской модели? - PullRequest
0 голосов
/ 05 октября 2010

Это моя первая попытка обновления базы данных с использованием LINQtoSQL. По крайней мере, это мое первое, если не считать учебники, за которыми я следовал. К сожалению, учебники, которые я нашел, предлагают не намного больше, чем обновление одной таблицы. Я пытаюсь обновить модель БД, которая немного сложнее.

У меня есть Stream таблица:

[Table]
public class Stream
{
    [HiddenInput(DisplayValue = false)]
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public long StreamID { get; set; }

    /** Other columns removed for brevity **/

    // relationship:
    private EntitySet<Stream2FieldTypes> _Stream2FieldTypes;
    [System.Data.Linq.Mapping.Association(Storage = "_Stream2FieldTypes", OtherKey = "StreamID")]
    public EntitySet<Stream2FieldTypes> Stream2FieldTypes
    {
        get { return this._Stream2FieldTypes; }
        set { this._Stream2FieldTypes.Assign(value); }
    }

И у меня есть Stream2FieldTypes таблица:

[Table]
public class Stream2FieldTypes
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
    public long s2fID { get; set; }
    public long StreamID { get; set; }     // FK

    /** other columns removed for brevity **/

    // relationship (one Stream2FieldTypes to many Streams) 
    private EntitySet<Stream> _Stream;
    [Association(Storage = "_Stream", ThisKey = "StreamID")]
    public EntitySet<Stream> Stream
    {
        get { return this._Stream; }
        set { this._Stream.Assign(value); }
    }

Теперь я пытаюсь обновить модель, чтобы я мог отправить обновления в хранилище для сохранения на DataContext. Я не могу обновить Stream.Stream2FieldTypes, потому что для get установлено частное EntitySet.

Как мне обновить Stream.Stream2FieldTypes, когда я не могу изменить Stream.Stream2FieldTypes, потому что это частный EntitySet <>?

Редактировать: код псевдо

В принципе, я думаю, что я должен иметь возможность обновлять таблицы Stream и Stream2FieldTypes, используя команду в моем действии редактирования, например:

myRepository.SaveStream(stream);

Я пытался сделать что-то вроде этого:

        if (ModelState.IsValid)
        {
            // Convert StreamEditModel to Stream
            var stream = new Genesis.Domain.Entities.Stream
            {
                StreamID = form.StreamID,
                StreamUrl = form.StreamUrl,
                StreamName = form.StreamName,
                StreamBody = form.StreamBody,
                StreamTitle = form.StreamTitle,
                StreamKeywords = form.StreamKeywords,
                StreamDescription = form.StreamDescription,
                Stream2FieldTypes = new EntitySet<Stream2FieldTypes>()
            };

            // Loop to convert Stream2FieldTypes to Steam2FieldTypesEditModel
            foreach (var item in form.Stream2FieldTypes)
            {
                var fieldTypeEntry = new Stream2FieldTypes
                {
                    FieldTypeID = item.FieldTypeID,
                    s2fID = item.s2fID,
                    s2fIsRequired = item.s2fIsRequired,
                    s2fLabel = item.s2fLabel,
                    StreamID = item.StreamID,
                };
                stream.Stream2FieldTypes.Add(fieldTypeEntry); // Add to list
            }

            genesisRepository.SaveStream(stream);

            return RedirectToAction("Index");
        }
        else 
        {
            return View(form);
        }

Когда я пытаюсь запустить этот код, я получаю эту ошибку:

Сведения об исключении: System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта.

Ошибка источника:

Строка 58: {

Строка 59: get {return this._Stream2FieldTypes; }

строка с ошибкой: строка 60: set {this._Stream2FieldTypes.Assign (value); }

Строка 61:}

Строка 62:

1 Ответ

3 голосов
/ 05 октября 2010

В вашем методе SaveStream вы устанавливаете свойство StreamID следующим образом StreamID = item.StreamID.Поскольку у вас есть идентификатор потока, я ожидаю, что вы пытаетесь изменить существующий класс Stream.Однако, глядя на ваш код, вы создаете новый.Я думаю, что проблема, с которой вы столкнулись, вызвана этим.

То, что вы должны сделать, это следующее:

  • Различать создание нового и изменение существующего объекта.
  • Постарайтесь максимально сократить использование свойств идентификатора.Работа с сущностями сама.Это делает ваш код намного чище и читабельнее.(Я всегда делаю свойства идентификатора внутренними, а EntitySet и EntityRef общедоступными).

Например, я думаю, что ваш SaveStream должен больше походить на следующий код.Если вы посмотрите внимательно, в этом коде отсутствуют строки, такие как:

  • FieldTypeID = item.FieldTypeID и
  • StreamID = form.StreamID.

Это потому, что это простоРабота.Вам необходимо сначала извлечь существующую сущность из базы данных и обновить ее.Вы не можете создать новый объект, установить его ID для существующей записи в базе данных и ожидать, что LINQ to SQL обновит эту запись для вас.Это не то, как проектируется LINQ to SQL.

Вот пример того, что может работать для вас:

public void SaveStream(StreamEditModel stream)
{
    if (!ModelState.IsValid)
    {
        return;
    }

    if (stream.Id == 0)
    {
        CreateStream(stream);
    }
    else
    {
        UpdateStream(stream);
    }
}

private void CreateStream(StreamEditModel form)
{
    var stream = new Stream();

    FillStream(stream, form);

    UpdateStream2FieldTypes(stream, form);

    genesisRepository.SubmitChanges();
}

private void UpdateStream(StreamEditModel form)
{
    var stream = genesisRepository.GetById(stream.StreamID);

    FillStream(stream, form);

    UpdateStream2FieldTypes(stream, form);

    genesisRepository.SubmitChanges();
}

private void FillStream(Stream stream, StreamEditModel form)
{
    stream.StreamUrl = form.StreamUrl;
    stream.StreamName = form.StreamName;
    stream.StreamBody = form.StreamBody;
    stream.StreamTitle = form.StreamTitle;
    stream.StreamKeywords = form.StreamKeywords;
    stream.StreamDescription = form.StreamDescription;
}

private void UpdateStream2FieldTypes(Stream stream,
    StreamEditModel form)
{
    var typesToDelete =
        from type in stream.Stream2FieldTypes
        let ids = form.Stream2FieldTypes.Select(t => t.FieldTypeID)
        where !ids.Contains(type.FieldTypeID)
        select type;

    genesisRepository.RemoveStream2FieldTypes(typesToDelete);

    var typesToAdd =
        from type in form.Stream2FieldTypes
        where type.FieldTypeID == 0
        select CreateStream2FieldTypes(type);

    foreach (var typeToAdd in typesToAdd)
    {
        stream.Stream2FieldTypes.Add(typeToAdd);
    }

    var formTypesToUpdate = 
        from type in form.Stream2FieldTypes
        where type.FieldTypeID != 0
        select type;

    foreach (var modelToUpdate in formTypesToUpdate)
    {
        var typeToUpdate = stream.Stream2FieldTypes.Single(
            t => t.FieldTypeID == modelToUpdate.FieldTypeID);

        FillStream2FieldTypes(typeToUpdate, typeToUpdate);
    }
}

private static  Stream2FieldTypes CreateStream2FieldTypes(
    Stream2FieldTypesEditModel form)
{
    var fieldType = new Stream2FieldTypes();

    FillStream2FieldTypes(fieldType, form);

    return fieldType;
}

private static void FillStream2FieldTypes(
    Stream2FieldTypes type, 
    Stream2FieldTypesEditModel item)
{
    type.s2fID = item.s2fID;
    type.s2fIsRequired = item.s2fIsRequired;
    type.s2fLabel = item.s2fLabel;
}

Cheers

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