我想加载 10 个最新产品,其中包含 5 个 A 类和 5 个 B 类。因此结果包含 5 个 A 类最新产品和 5 个 B 类最新产品。
通常我可以使用这两个来做到这一点:
var listA = await (
from p in db.Set<Product>()
where p.Category == "A"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var listB = await (
from p in db.Set<Product>()
where p.Category == "B"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var result = listA.Concat(listB);
Run Code Online (Sandbox Code Playgroud)
但是正如您所看到的,这段代码需要对数据库进行 2 次调用。
我怎样才能得到结果,只使用 1 个数据库调用?
在这样的子实体上设置外键时:
modelBuilder.Entity<Child>()
.HasOne(c => c.Parent)
.WithMany(p => p.Children)
.HasForeignKey(c => c.ParentId)
.OnDelete(DeleteBehavior.Cascade);
Run Code Online (Sandbox Code Playgroud)
我能够配置约束的“ON DELETE”行为。由此产生的迁移看起来像:
migrationBuilder.CreateTable(
name: "Child",
columns: table => new
{
Id = table.Column<Guid>(nullable: false),
ParentId = table.Column<Guid>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Child", x => x.Id);
table.ForeignKey(
name: "FK_Child_Parent_ParentId",
column: x => x.ParentId,
principalTable: "Parent",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
Run Code Online (Sandbox Code Playgroud)
在生成的迁移中,我可以直接编辑 onUpdate 行为,如方法签名中所示:
public virtual OperationBuilder<AddForeignKeyOperation> ForeignKey(
[NotNull] string name,
[NotNull] Expression<Func<TColumns, object>> column,
[NotNull] string principalTable,
[NotNull] string principalColumn,
[CanBeNull] string principalSchema = null,
ReferentialAction onUpdate …Run Code Online (Sandbox Code Playgroud) 我有以下代码,我需要根据条件将新项目添加到导航属性中。类的NotificationToUser属性Notification是IEnumerable类型。
Notification notification = new Notification
{
DateCreated = DateTime.Now,
ToUsers = _context.PeerGroupMemberships
.Where(pg => pg.PeerGroup.SubmissionId == assessmentItem.SubmissionId && pg.UserId != currentUser.Id)
.Select(pg => new NotificationToUser { IsRead = false, UserId = pg.UserId })
};
if(submissionOwnerId != currentUser.Id)
{
notification.ToUsers = notification.ToUsers.Append(new NotificationToUser { IsRead = false, UserId = submissionOwnerId });
}
_context.Notifications.Add(notification);
_context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
但是,向导航属性添加新项目会导致此错误:
System.InvalidOperationException: '实体类型'通知'上的导航属性'ToUsers'的类型是'AppendPrepend1Iterator',它没有实现ICollection。集合导航属性必须实现目标类型的 ICollection<>。
通知类是:
public class Notification
{
[Key]
public int Id { get; set; }
public string Text …Run Code Online (Sandbox Code Playgroud) 直到.donet core 2.2中使用的EF核心版本,在该.Add命令之后,EF用一个大的负数填充key列。
3.0 升级后,这种情况不再发生。
这是代码:
var appointment = new Appointment
{
Date = DateTime.Today,
ProfessionalId = schedule.ProfessionalId
};
await service.AddAsync(appointment);
string message = null;
if (service.AddLastPrescription(appointment.Id, schedule.PacienteId))
....
Run Code Online (Sandbox Code Playgroud)
问题是现在“appointment.Id”为零,对服务功能的调用将失败(FK 错误)。
这种行为在 3.0 中是预期的?
添加异步函数
private DbSet<T> dbSet;
public async Task AddAsync(T t)
{
await dbSet.AddAsync(t);
}
Run Code Online (Sandbox Code Playgroud)
其中 T 是 ModelBase:
public class ModelBase
{
[Key]
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; } …Run Code Online (Sandbox Code Playgroud) 我在 .net 核心项目中使用 EF 核心。从 ef 上下文中获取数据后,对象的实体(一对多等)将自动加载。
这是我的代码:
public TimeSheetActivity Get(int id)
{
DataSets.TimeSheetActivity dbActivity = db.TimeSheetActivities
.Include(k => k.ProjectFile)
.Include(k => k.MeasurementUnit)
.Include(k => k.TypeOfWork)
.Include(k => k.TimeSheetProject)
.FirstOrDefault(k => k.ID == id);
return dbActivity == null ? null : _mapper.Map<TimeSheetActivity>(dbActivity);
}
public Project GetActivityProject(int id)
{
//db.SaveChanges();
TimeSheetActivity activity = Get(id);
if (activity == null)
{
return null;
}
var dbTimeSheetProject = db.TimeSheetProjects.First(k => k.ID == activity.TimeSheetProjectId);
var dbProject = db.Projects.First(k => k.ID == dbTimeSheetProject.ProjectId);
// PROBLEM HERE …Run Code Online (Sandbox Code Playgroud) 我目前正在 .NET Core 中开发原型,为了简单起见,我使用了 Docker/Heroku。
我注意到的是,当尝试通过 运行迁移时heroku dotnet run ef database update,dotnetCLI 不可用。我很快注意到这是因为我的最终映像只有运行时,而不是 sdk。我的问题是:为了能够运行迁移,同时拥有仅运行运行时的较轻映像,什么最有意义?我是否因为只有运行时而大做文章?
这就是我当前的图像,以便能够像我现在一样运行迁移:
FROM mcr.microsoft.com/dotnet/core/sdk:3.0
WORKDIR /app
COPY --from=build-env /app/out ./
RUN dotnet tool install --global dotnet-ef
# Set ASPNETCORE_URLS to run the app on the port Heroku exposes.
# Kestrel run by default on 5000/1 and Heroku doesn't allow that.
CMD ASPNETCORE_URLS=http://*:$PORT dotnet Lazarus.dll
Run Code Online (Sandbox Code Playgroud)
我有 SDK 并且必须在生产映像中安装 EF CLI 感觉不对,所以欢迎任何见解!
我在 .Net Core 3.1 中使用 EF Core
我有一个简单的客户端事件关系示例:
public class BaseEntity
{
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
}
public class Client : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class Event : BaseEntity
{
public DateTime …Run Code Online (Sandbox Code Playgroud) 如果字符串是在 C# 中插入的,如何检查接受字符串的方法内部?
// String interpolation
var author = db.Authors.FromSql($"SELECT * From Authors Where AuthorId = {id}").FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
如果内联提供给 FromSql 方法调用,Entity Framework Core 只会参数化内插字符串。在 FromSql 方法调用之外声明的内插字符串将不会被解析为参数占位符。实际上,您将直接将串联字符串传递给数据库,这存在 SQL 注入风险。
以下示例是危险的,不应使用:
var sql = $"SELECT * From Authors Where AuthorId = {id}";
var author = db.Authors.FromSql(sql).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
在阅读上面的摘录之前,我认为在一个方法中我得到了一个字符串并且不可能知道它是如何构造的。摘录让我相信这在某种程度上是可能的。
我在 C# 应用程序中使用实体框架,并且使用延迟加载。我们注意到一个查询对我们的 CPU 有非常大的影响,它只计算一个总和。在调试由实体框架生成的查询时,它会创建一个INNER JOIN (SELECT ...性能不佳的查询。当我手动将查询更改为正确的 JOIN 时,查询时间从 1.3 秒变为 0.03 秒。
让我用我的代码的简化版本来说明它。
public decimal GetPortfolioValue(Guid portfolioId)
{
var value = DbContext.Portfolios
.Where( x => x.Id.Equals(portfolioId) )
.SelectMany( p => p.Items
.Where( i => i.Status == ItemStatusConstants.Subscribed
&& _activeStatuses.Contains( i.Category.Status ) )
)
.Select( i => i.Amount )
.DefaultIfEmpty(0)
.Sum();
return value;
}
Run Code Online (Sandbox Code Playgroud)
这将生成一个查询,该查询选择总和,但对连接在一起的两个表的 SELECT 进行内部连接。我在这里为生成的查询创建了一个 pastebin ,不会污染这个问题,但缩短的版本是:
SELECT ...
FROM `portfolios` AS `Extent1`
INNER JOIN (SELECT
`Extent2`.*,
`Extent3`.*
FROM `items` AS `Extent2`
INNER …Run Code Online (Sandbox Code Playgroud) 我想创建一个内存中的 SQLite 数据库。
这是startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<TestDBContext>().AddEntityFrameworkSqlite();
}
Run Code Online (Sandbox Code Playgroud)
这是数据库的模型:
public class TestModel
{
public string UserName { get; set; }
[Key]
public string id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是数据库的DBContext:
public class TestDBContext : DbContext
{
public virtual DbSet<TestModel> Test { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=:memory:");
}
}
Run Code Online (Sandbox Code Playgroud)
这是控制器:
private readonly TestDBContext TestDBContext;
public HomeController(ILogger<HomeController> logger,TestDBContext _TestDBContext)
{
_logger = logger;
this.TestDBContext = _TestDBContext;
}
public IActionResult Index() …Run Code Online (Sandbox Code Playgroud) entity-framework entity-framework-core .net-core asp.net-core
entity-framework ×10
c# ×8
asp.net-core ×4
linq ×3
.net ×1
.net-core ×1
arguments ×1
asp.net ×1
core ×1
ef-core-2.1 ×1
ef-core-2.2 ×1
heroku ×1
mysql ×1
parameters ×1
performance ×1
sql-server ×1