繁体   English   中英

实体框架关系

[英]Entity framework relationships

我有以下三个实体:

public class Dog
{
    public int DogId { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public bool Checked { get; set; }
    public string DogImage { get; set; }

    public virtual ICollection<Result> Results { get; set; }
}

public class Event
{
    public int EventId { get; set; }
    public string EventName { get; set; }
    public string EventLocation { get; set; }
    public string EventType { get; set; } 
    public string EventDate { get; set; } 

    public virtual ICollection<Result> Results { get; set; }
}

public class Result
{
    public int ResultId { get; set; }
    public int Track { get; set; }
    public int Obedience { get; set; }
    public int Protection { get; set; }

    [ForeignKey("Dog")]
    public int DogId { get; set; }
    public virtual Dog Dog { get; set; }

    [ForeignKey("Event")]
    public int EventId { get; set; }      
    public virtual Event Event { get; set; }
}

我以前一直在这里得到帮助,以便进行这样的设置。 尝试创建多对多关系时出现实体框架错误

因此,我现在想的result是将这些类联系在一起的“胶水”,其中包含指向其他两个表的外键。

我几天来一直在努力实现以下目标:

  1. 创建一个事件。
  2. 将狗添加到活动中。
  3. 将结果添加到参加ChoosenEvent的狗中。

可以说我创建了一个这样的事件:

[HttpPost]
public ActionResult CreateEvent(Event newEvent)
{
    newEvent.EventDate = newEvent.EventDate.ToString();
    _ef.AddEvent(newEvent);

    return View();
}

现在,我想下一步将是向此事件添加狗的列表,并且为了做到这一点,我需要以某种方式使用我的结果类,因为那是“胶水”类。 请让我知道我是否在正确的轨道上。

我只是使用fluent方法完成此操作的(当我发现我发现您可以使用fluent进行所有操作时,但不能使用批注,因此我没有研究它们),以下内容在我的Unit实体之间创建了很多对很多和我的UnitService实体:

modelBuilder.Entity<Unit>()
            .HasMany<UnitService>(u => u.Services)
            .WithMany(us => us.Units);

此代码位于protected override void OnModelCreating(DbModelBuilder modelBuilder)方法中。

在您的情况下, EventUnitDogUnitService

哎呀,您根本不需要它,您的“联接”表就是您的结果表,就我而言,我不在乎联接表,因此它全都隐藏了。 也许像这样:

   modelBuilder.Entity<Result>()
               .HasMany<Event>(e => e.Results);
   modelBuilder.Entity<Result>()
               .HasMany<Dog>(d => d.Results);

进行多对多的关系(例如您的工作方式)并不是一个好主意。 看这里

为了获得正确的多对多关系(以正确的方式映射到数据库中),它没有陷阱,我可以这样尝试:

public class Dog {}
public class Event {}

public class Result {}

// This is a linking table between Dog and Results
public class DogResult
{
    public int Id {get;set;}
    public int DogId {get;set;}
    public int ResultId {get;set;}
}

// This is a linking table between Events and Results
public class EventResult
{
    public int Id {get;set;}
    public int EventId {get;set;}
    public int ResultId {get;set;}
}

现在,当您编写查询时,您可以执行以下操作:

using (var context = new DbContext())
{
   var dogs = context.Dogs();
   var dogResults = context.DogResults();
   var results = context.Results();

   var dogsAndResults = dogs.Join(
          dogResults,
          d => d.Id,
          r => r.DogId,
          (dog, dogResult) => new { dog, dogResult })
       .Join(
          results,
          a => a.dogResult.ResultId,
          r => r.Id,
          (anon, result) => new { anon.dog, result });
}

看起来有点讨厌,但它会给您返回一个包含Dog及其相关Result的匿名对象的列表。 但是显然最好在存储过程中执行此操作:

using (var context = new DbContext())
{
    var results = context.Database.ExecuteStoreQuery<SomeResultDto>("SELECT * .... JOIN ... ");
}

这很干净,因为您正在使用SQL。

这是一种更复杂的处理方式。 但是性能要高得多,尤其是如果您完全了解实体框架如何执行LINQ。

显然,如果要创建以下链接:

using (var context = new DbContext()) 
{
    context.Dogs.AddRange(dogs); // dogs being a list of dog entities
    context.Results.AddRange(results); // events being a list of results entities

    context.DogResults.AddRange(dogResults); // a list of the links
}

如何创建这些链接完全取决于您。 要将其也转换为存储,您需要创建一些自定义的用户定义表类型并将其用作表值参数。

var dogResults = dogs.SelectMany( d => results.Select ( r => new DogResult { DogId = d.Id, ResultId = r.Id } ) );

那是LINQ查询的野兽,基本上它会获取每条狗并将其链接到每条结果。 在LinqPad运行它,并Dump值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM