使用EF和LINQ减少到数据库的次数

时间:2013-05-06 19:51:11

标签: c# entity-framework linq-to-sql asp.net-mvc-4

请考虑以下代码:

// check record exists

Adjuster adj = new Adjuster();

if (db.Adjusters.Where(x => x.userID == user.id).Any())
{
    adj = db.Adjusters.Where(x => x.userID == user.id).FirstOrDefault();
}
else
{
    // create adjuster record
    adj.id = Guid.NewGuid();
    adj.userID = user.id;

    db.Adjusters.InsertOnSubmit(adj);
}

请注意我首先拨打.Any(),然后拨打.FirstOrDefault()。这将是对数据库的两个单独查询,对吧?我怎样才能将其限制为一个?

现在,请考虑以下代码:

adj.isPropertyAdjuster = user.SomeEntity.someProperty;
adj.isCasualityLiabilityAdjuster = user.SomeEntity.someProperty;
adj.isLargeLossAdjuster = user.SomeEntity.someProperty;

db.SubmitChanges();

使用LINQ / EF,我可以访问与彼此有关系的不同实体。但是,每次执行此操作时都不会对数据库进行多次调用吗?例如,这些是对数据库的所有三个单独调用吗?

adj.isPropertyAdjuster = user.SomeEntity.someProperty;
adj.isCasualityLiabilityAdjuster = user.SomeEntity.someProperty;
adj.isLargeLossAdjuster = user.SomeEntity.someProperty;

如何将此限制为对数据库的单一调用?我假设唯一的方法是像这样实例化一个对象:

SomeEntity obj = user.SomeEntity;

然后,调用这样的属性:

adj.isPropertyAdjuster = obj.someProperty;

你有什么想法?

3 个答案:

答案 0 :(得分:5)

关于第一个问题:

var adjuster = db.Adjusters.FirstOrDefault(x => x.userID == user.id);
if (adjuster == null)
{
  // create adjuster record
    adjuster.id = Guid.NewGuid();
    adjuster.userID = user.id;

    db.Adjusters.InsertOnSubmit(adjuster);
}

关于第二个,我相信EF在加载数据时会缓存数据,因此您首次访问user.SomeEntity.someProperty将会访问数据库,但所有后续访问都不会。不过,您可能希望查看Eager Loading

答案 1 :(得分:2)

对于您的第一个示例,您只需致电FirstOrDefault()并完全离开Any()

Adjuster adj = db.Adjusters.Where(x => x.userID == user.id).FirstOrDefault();

if (adj == null)
{
  // create adjuster record
  adj.id = Guid.NewGuid();
  adj.userID = user.id;

  db.Adjusters.InsertOnSubmit(adj);
}

至于访问实体的导航属性是否导致重复往返数据库,答案是(谢天谢地!)no。根据您是否启用了延迟加载,该属性的值将在首次创建时与实体的其余部分一起加载,或者在第一次访问该属性时加载,然后缓存以供将来使用。

所以,你的例子......

adj.isPropertyAdjuster = user.SomeEntity.someProperty;
adj.isCasualityLiabilityAdjuster = user.SomeEntity.someProperty;
adj.isLargeLossAdjuster = user.SomeEntity.someProperty;

...最多只需要一个额外的数据库查询,如果您在第一次加载user时使用了预先加载,则可能不会这样。

答案 2 :(得分:2)

您可以使用

修复第一个代码
Adjuster adj = db.Adjusters.Where(x => x.userID == user.id).FirstOrDefault();

if (adj == null)
{
    // create adjuster record
    adj = new Adjuster();
    adj.id = Guid.NewGuid();
    adj.userID = user.id;

    db.Adjusters.InsertOnSubmit(adj);
}

第二部分没问题。

adj.isPropertyAdjuster = user.SomeEntity.someProperty;
adj.isCasualityLiabilityAdjuster = user.SomeEntity.someProperty;
adj.isLargeLossAdjuster = user.SomeEntity.someProperty;

db.SubmitChanges();

一旦加载一次,它就不应该继续从数据库中提取一些内容。此外,在调用提交之前,它不会保存任何内容。