首先使用Entity Framework代码获取外键值

Oxy*_*ron 3 c# database entity-framework ef-code-first

我有两个型号,一个用于设备类型,另一个用于设备问题.这里的关系是一个(DeviceType)到很多(DeviceIssues).以下是模型:

public class DeviceType : ModelBase
{
    public string Manufacture { get; set; }
    public DeviceTypes Type { get; set; }
    public string Model { get; set; }

    public virtual ICollection<DeviceIssue> Issues { get; set; }
}

public class DeviceIssue : ModelBase
{
    public string Description { get; set; }
    public decimal RepairCost { get; set; }

    public int DeviceTypeId { get; set; }
    public virtual DeviceType DeviceType { get; set; }
}

public abstract class ModelBase
{
    public int Id { get; set; }
    public Guid Guid { get; set; }
    public DateTime FirstCreated { get; set; }
    public string LastUpdateUser { get; set; }
    public DateTime LastUpdateDt { get; set; }
    public bool IsDeleted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我必须使用种子方法填充多个实体的数据库,并且它们的外键完好无损.但是,当我获得设备类型列表时,我也没有获得每个设备的相关问题列表.但是,我正在使用AutoMapper,而调试存储查询结果的变量也不会显示数据.这是我用来调用的代码:

var result = new List<DeviceTypeDataContract>();
using (var context = new DSPEntities())
{
    var devices = context.DeviceTypes;
    foreach (var device in devices)
    {
        //var issues = context.DeviceIssues.Where(i => i.DeviceTypeId == device.Id).ToList();

        var devi = Mapper.Map<DeviceType, DeviceTypeDataContract>(device);
        result.Add(devi);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在如所述的,在调试时,检查变量deviceforeach(var device in devices),显示了以下类似的结果,每次:

device.Issues = null,
device.manufacture = "Apple",
device.Model = "iPhone 3S",
device.Type = DeviceTypes.SmartPhone,
Run Code Online (Sandbox Code Playgroud)

如果您在我的代码中注意到有一行注释掉的代码.这是注释,因为它抛出以下内部异常:

{"已经有一个与此命令关联的打开DataReader,必须先关闭它."}

我不知道这是否与我的具体问题有关.

我的问题是,我如何从这些关系中检索数据?

注意:关系确实存在,因为在foreach语句之外,调用以下内容:

var issues = context.DeviceIssues.Where(i => i.DeviceTypeId == 1).ToList();
Run Code Online (Sandbox Code Playgroud)

给出以下结果:

issues[6].Description = "Water Damage",
issues[6].RepairCost = 0.00,
issues[6].DeviceTypeId = 1,
issues[6].DeviceType = [+]{Data.Model.DeviceType},
// The last property holds values similar to above.
// Except now the list of issues is populated.
Run Code Online (Sandbox Code Playgroud)

请注意上面的评论:"除了现在填写的问题列表."

Bra*_*tie 6

当你装饰与virtual你的关联推断他们是懒惰加载.这意味着DeviceTypes已加载主要集合(在本例中),但在您尝试访问它之前,Issues不会填充任何信息.

有多种方法可以解决这个问题,但最简单(也是最有效)的方法是在需要时使用该Include方法加载关联.例如

var devices = context.DeviceTypes.Include(x => x.Issues);
Run Code Online (Sandbox Code Playgroud)

这将加载原始collection(DeviceTypes)以及Issues为每种类型填充.这通常是最好的方式,因为您只需要获取所需信息,以便在需要时完成工作单元.

但是,如果您发现这很常见,则可以始终在DbContext构造函数中调整延迟加载:

public DSPEntities()
{
    this.Configuration.LazyLoadingEnabled = false;
}
Run Code Online (Sandbox Code Playgroud)