簡體   English   中英

持久實體框架嵌套/相關實體

[英]Persisting Entity Framework nested/related entities

我有以下實體:

public class ModuleCriteria
{
    public int ModuleCriteriaId { get; set; }

    public string Criteria { get; set; }

    public List<ModuleCriteriaLookup> ModuleCriteriaLookups { get; set; 
}
}

public class ModuleCriteriaLookup
{
    public int ModuleCriteriaLookupId { get; set; }

    public int ModuleCriteriaId { get; set; } // ** (Foreign Key) **

    public int SiteId { get; set; }

    public string CategoryId { get; set; }

    public ModuleCriteria ModuleCriteria { get; set; }
}

我的Context類中有以下EF配置(為簡潔起見進行了編輯):

protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
    base.OnModelCreating( modelBuilder );

    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<ModuleCriteriaLookup>().HasRequired( mc => mc.ModuleCriteria );

    // I tried adding the below line but it made no difference.
    //modelBuilder.Entity<ModuleCriteria>().HasMany( mc => mc.ModuleCriteriaLookups );
}

...並且在Context類中定義了以下DbSet屬性:

public DbSet<ModuleCriteria> ModuleCriteria { get; set; }

public DbSet<ModuleCriteriaLookup> ModuleCriteriaLookup { get; set; }

我有一個CriteriaRepository類,該類具有Save方法,用於持久Save我的ModuleCriteria實體的更改:

public void Save( ModuleCriteria moduleCriteria )
{
    using ( var ctx = new MyAppContext() )
    {
        ctx.Entry( moduleCriteria ).State = moduleCriteria.ModuleCriteriaId == 0 ? EntityState.Added : EntityState.Modified;

        ctx.SaveChanges();
    }
}

沒有ModuleCriteria對象也可以存在ModuleCriteriaLookup對象,但是ModuleCriteriaLookup對象必須與現有的ModuleCriteria對象相關(與ModuleCriteriaId相關)。

您可以具有多個ModuleCriteraLookup對象,這些對象都與同一個ModuleCriteria對象相關。

我想要並期望使用EF的行為是:

1)如果我創建一個新的ModuleCriteria對象(沒有任何ModuleCriteriaLookups ),請在我的存儲庫中調用Save方法,我希望在數據庫中看到新的ModuleCriteria記錄,而在數據庫中沒有相關的ModuleCriteriaLookup記錄。

2)如果我創建一個新的ModuleCriteria對象並為其分配一個List<ModuleCriteriaLookup> ,請在我的存儲庫中調用Save方法,我希望在db中看到新的ModuleCriteria記錄,並在db中看到ModuleCriteria x個新的ModuleCriteriaLookup行。特定的ModuleCriteria

3)如果我添加/編輯/刪除任何的ModuleCriteriaLookup是與我的一個對象ModuleCriteria對象,然后調用Save的方法在我的倉庫,我希望看到任何的ModuleCriteria的刪除ModuleCriteriaLookup對象從下列位置移除數據庫,添加任何新的和編輯的只是為了得到更新。

因此,我只需要擔心的是,對於給定的ModuleCriteria ,無論ModuleCriteria.ModuleCriteriaLookups屬性包含什么,只需在存儲庫中為ModuleCriteria對象調用Save方法,這就會反映在數據庫的2個表中。

不幸的是,目前,如果我要添加一個新的帶有關聯的List<ModuleCriteriaLookup> ModuleCriteria對象,它將很好地在數據庫中添加ModuleCriteria和x ModuleCriteriaLookup行。 但是,當我要編輯或刪除ModuleCriteria.ModuleCriteriaLookups屬性中的條目時,這並沒有反映在數據庫中。 ModuleCriteriaLookups行沒有任何ModuleCriteriaLookups

我不確定問題出在哪里,是否是EF映射配置,還是與存儲庫的工作方式有關?

問題位於存儲庫中。 DbContext需要意識到實體的存在。 因此,在編輯和/或刪除實體時,首先需要從數據庫中獲取實體。

描述明確指出:

.Entry屬性從上下文返回由上下文跟蹤的對象。

由於您是在創建上下文之后直接使用此屬性的,因此上下文不會跟蹤這些實體,因此不會知道某些更改。 因此無法生成正確的SQL語句。

有幾種方法可以解決此問題,具體取決於設計的其余部分。

刪除它的一種方法是:

    public void DeleteModuleCriteriaLookup(ModuleCriteriaLookup[] lookups)
    {
        using (var ctx = new MyAppContext())
        {
            var moduleCriteriaId = lookups.First().ModuleCriteriaId;

            var moduleCritria = (
                from criteria in ctx.ModuleCriteria
                where criteria.ModuleCriteriaId == moduleCriteriaId
                select criteria
                ).Single();

            var lookupIdsToDelete = lookups.Select(l => l.ModuleCriteriaLookupId);

            var lookupsToDelete = (
                from lookup in moduleCritria.ModuleCriteriaLookups
                where lookupIdsToDelete.Contains(lookup.ModuleCriteriaLookupId)
                select lookup
                ).ToArray();

            foreach (var lookup in lookupsToDelete)
            {
                moduleCritria.ModuleCriteriaLookups.Remove(lookup);
            }

            ctx.SaveChanges();
        }
    }

暫無
暫無

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

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