【问题标题】:Entity Framework Many to Many List Table Association实体框架多对多列表关联
【发布时间】:2014-02-26 15:10:07
【问题描述】:

我有以下类(我只显示重要的属性):

public class TypeLocation
{
    [Key]
    public int Id {get; set;}
    public string Country {get; set;}
    public string State {get; set;}
    public string County {get; set;}
    public string City {get; set;}

    public List<Offer> Offers {get; set; }
    public TypeLocation()
    {
        this.Offers = new List<Offer>();
    }
}

public class Offer
{
    public int Id { get; set; }

    public ICollection<TypeLocation> LocationsToPublish { get; set; }
}

这会在数据库中创建以下内容:

我的问题/问题

TypeLocations 表预先填充了国家/州/县/城市记录的静态列表,其中一个或多个可以与 LocationsToPublish 属性中的优惠相关联。当我尝试使用以下代码添加位置时,Entity Framework 在TypeLocation 表中添加一条新记录,然后通过在OfferTypeLocations 表中添加一条记录来建立关联。

    public static bool AddPublishLocation(int id, List<TypeLocation> locations)
    {
        try
        {
            using (AppDbContext db = new AppDbContext())
            {
                Offer Offer = db.Offers
                    .Include("LocationsToPublish")
                    .Where(u => u.Id == id)
                    .FirstOrDefault<Offer>();

                //Add new locations
                foreach (TypeLocation loc in locations)
                {
                    Offer.LocationsToPublish.Add(loc);
                }
                db.SaveChanges();
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

我不希望将新记录添加到 TypeLocations 表中,而只是在 OfferTypeLocations 表中创建关联的关系记录。对我做错了什么有任何想法吗?

解决方案

感谢@Mick 在下面的回答,我找到了解决方案。

    public static bool AddPublishLocation(int id, List<TypeLocation> locations)
    {
        try
        {
            using (AppDbContext db = new AppDbContext())
            {
                Offer Offer = db.Offers
                    .Include("LocationsToPublish")
                    .Where(u => u.Id == id)
                    .FirstOrDefault<Offer>();

                //Add new locations
                foreach (TypeLocation loc in locations)
                {
                    //SOLUTION
                    TypeLocation ExistingLoc = db.AppLocations.Where(l => l.Id == loc.Id).FirstOrDefault<TypeLocation>();

                    Offer.LocationsToPublish.Add(loc);
                }
                db.SaveChanges();
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

发生的情况是,使用现有的 AppDbContext,我从 TypeLocations 表中检索现有记录(此处标识为 AppLocations),然后将其添加到 LocationsToPublish 实体中。

关键是我要使用当前的 AppDbContext(用 Using() 语句包装)来完成所有工作。此上下文之外的任何数据都是纯粹的信息性数据,用于协助在 AppDbContext 上下文中发生的记录查找或创建。我希望这是有道理的。

【问题讨论】:

  • 如果您打开分析器,您会看到此解决方案会为添加的每个位置生成额外的查询。它会起作用,但是它会比下面的解决方案慢很多。
  • List 实际上是从网页上发布的数据生成的,因此没有任何上下文可以传入。实际上,我们不应该在任何时间点传入太多的 TypeLocation ,最多 10-15 个。

标签: c# entity-framework


【解决方案1】:

TypeLocations 是从不同的 AppDbContext 加载的,它们被视为您在方法中构建的 AppDbContext 中的新实体。要修复:-

  1. 假设位置已从您的方法之外的 AppDbContext 实例中分离出来,您可以将这些实体附加到新上下文。 或
  2. 传入用于将位置加载到您的 AddPublishLocation 方法的 AppDbContext。

我会选择 2:-

public static bool AddPublishLocation(AppDbContext db, int id, List<TypeLocation> locations)
{
    try
    {
        Offer Offer = db.Offers
            .Include("LocationsToPublish")
            .Where(u => u.Id == id)
            .FirstOrDefault<Offer>();

        //Add new locations
        foreach (TypeLocation loc in locations)
        {
            Offer.LocationsToPublish.Add(loc);
        }
        db.SaveChanges();
        return true;
    }
    catch
    {
        return false;
    }
}

【讨论】:

  • 我不明白它们是如何从不同的 AppDbContext 加载的。你有更多关于这方面的信息吗?
  • 我想到了你的答案,找到了解决办法!基本上,我需要从与我要添加的位置的 ID 匹配的表中检索现有的 TypeLocation 记录。我已经更新了我的问题。
  • 每次实例化一个新的 AppDbContext 实例时,该实例跟踪通过上下文加载的所有实体,未通过该 AppDbContext 实例加载的实体在添加时将被视为新实体到上下文。您的原始代码清楚地传递了 TypeLocations,该 TypeLocations 必须使用 AppDbContext 的不同实例在其他地方加载。为了使实体被视为现有实体,需要在您的方法中通过 AppDbContext 附加或加载它们,这就是您的解决方案有效的原因
  • 更新了我的答案,尝试更简洁一点
  • 感谢@Mick 的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2012-05-28
  • 1970-01-01
  • 2017-01-28
相关资源
最近更新 更多