我有以下模型:
[Table("Experiments")]
public class Experiment
{
...
public virtual ICollection<ExperimentType> ExperimentTypes { get; set; }
public Experiment()
{
ExperimentTypes = new List<ExperimentType>();
}
}
[Table("ExperimentTypes")]
public class ExperimentType
{
...
public virtual ICollection<Experiment> Experiments { get; set; }
public ExperimentType()
{
Experiments = new List<Experiments>();
}
}
DbSet包含:
public DbSet<Experiment> Experiments { get; set; }
public DbSet<ExperimentType> ExperimentTypes{ get; set; }
这将在SQL上创建一个名为ExperimentExperimentTypes的表。
现在,我想执行LINQ连接,例如:
var query =
from e in database.Experiments
join eet in database.ExperimentExperimentTypes on eet.Experiment_Id equals eet.ExperimentType_Id ...
但是很明显,数据库.ExperimentExperimentTypes在代码中无法识别。
为了告诉代码有此表,我做了很多事情,我也尝试创建相应的c#类,但没有得到任何结果。
如何实现?
答案 0 :(得分:0)
因此,您有两个表:Experiment
和ExperimentType
。这两者之间存在多对多的关系:每个Experiment
都是零个或多个ExperimentTypes
的实验;每个ExperimentType
都是零个或多个Experiments
的类型。
这可以在您的类定义中看到。两侧的virtual ICollection<...>
表示多对多关系。
在关系数据库中,此多对多关系是使用联结表实现的。但是,在实体框架中,您很少看到联结表。它在您的数据库中,但是,您无法使用DbContext访问它
但是我要如何在“实验”和“ 如果我无法访问联结表,则为ExperimentTypes?
好吧,维尼熊应该回到他的思考地点。他不想联接表,他希望所有(或一些)Experiments
,每个都具有其ExperimentTypes
的所有(或部分)。
那么为什么不只使用ICollection<...>
查询呢?
var experiments = myDbContext.Experiments
.Where(experiment => ...) // only if you don't want all experiments
.Select(experiment => new
{ // Select only the properties you actually plan to use
Id = experiment.Id,
Name = experiment.Name,
...
// get all or some of its ExperimentTypes
ExperimentTypes = experiment.ExperimentTypes
.Where(experimentType => ...) // only if you don't want all experiment types
.Select(experimentType => new
{
// again: select only the properties you plan to use
Id = experimentType.Id,
...
})
.ToList(),
});
实体框架非常了解,它知道需要使用联结表进行三次联接,并将执行这种三次联接。
在内部,这将是一个 GroupJoin ,您将获得Experiments
,每个都有其ExperimentTypes
。您甚至可以获得还没有任何实验类型的实验。
如果您确实要使用inner join
,则必须使用它们的ExperimentTypes来简化实验。这是通过overload of SelectMany that has a resultSelector as parameter
// flatten the Experiments with their experimentTypes
var flatInnerJoin = myDbContext.Experiments.SelectMany(experiment => experiment.ExperimentTypes,
// from each experiment and one of its experimentTypes make one new object
(experiment, experimentType) => new
{
ExperimentId = experiment.Id,
ExperimentTypeId = experimentType.Id,
...
});
})
Nota bene!这样,您就不会像标准内部联接中那样获得没有ExperimentTypes的实验。