簡體   English   中英

在LINQtoSQL中,如何通過編輯父模型來更新子關系?

[英]In LINQtoSQL, how can I update child relationships by editing the parent model?

這是我第一次嘗試使用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 <>?

編輯:偽代碼

基本上,我認為我應該能夠通過在Edit Action中使用如下命令來更新StreamStream2FieldTypes表:

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行:

在您的SaveStream方法中,您可以像這樣設置StreamID屬性: StreamID = item.StreamID 因為您具有Stream ID,所以我希望您嘗試更改現有的Stream類。 但是,查看代碼時,您正在創建一個新代碼。 我認為您遇到的問題是由此引起的。

您應該執行以下操作:

  • 區分創建新實體和變異現有實體。
  • 盡量減少對ID屬性的使用。 與實體本身一起工作。 這使您的代碼更加清晰易讀。 (我總是將ID屬性EntitySet內部,並將EntitySetEntityRef公共)。

例如,我認為您的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;
}

干杯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM