我的公司正在转向微服务,作为这一转变的一部分,devops 正在使用 VSTS 和 GIT 在 Azure 中建立 CI/CD 构建发布管道。
当前管理迁移的模型是为开发人员提供 2 个独立 git 存储库中的 2 个项目。
项目 1 - API 服务项目 - .NET Framework / .Net Core
项目 2 - 使用迁移 API 基于 EF6 的数据库项目
这些项目具有基于存储库的完全独立的发布管道。因此,当您向 master 创建拉取请求时,管道会构建并发布项目。
这个新架构还支持蓝绿部署,我们的应用程序服务在多个节点上运行。
我们遇到的问题是,通过这种设置,我们基本上必须手动编写迁移代码,并且无法使用 EF Core 中提供的任何工具。
我读过的大多数文章和文档都显示从应用程序启动时运行迁移,但是如果您有多个应用程序服务节点,如何防止 2 个节点运行迁移?
我看过的其他文章显示了将迁移移动到一个单独的项目中,但该项目需要引用其中包含 dbcontext 的项目。在我公司的设置中这是不可能的。我们也不能做相反的事情,因为将 dbcontext 移动到数据库项目中会阻止我们在 api 服务项目中引用它。
有什么办法可以让 EF Core 支持这个模型吗?
在多节点应用服务上使用 EF Core 迁移实现蓝绿部署的首选方法是什么?
为什么我最初update-database
失败了,我需要在数据库表类中更改什么才能使其工作?
onDelete: ReferentialAction.Cascade
当然,我可以将迁移脚本中的更改为onDelete: ReferentialAction.NoAction
,但随后我将在应用程序中面临其他问题。我正在寻找一种解决方案,无需编辑add-migration
. 换句话说,我愿意更改我的数据库架构。
我想要的行为是,当我删除 a 时Product
,关联的ProductPropertyOptionForProducts
也会被删除,但反之则不然,而不是ProductPropertyOption
与 关联的ProductPropertyOptionForProducts
。
这是迁移输出错误消息:
在表“PropertyOptionsForProducts”上引入外键约束“FK_PropertyOptionsForProducts_ProductPropertyOptions_ProductPropertyOptionId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束或索引。请参阅以前的错误。
生成的导致错误的 SQL 命令:
CREATE TABLE[PropertyOptionsForProducts] (
[Id] int NOT NULL IDENTITY,
[CustomNumberValue] decimal (18, 2) NOT NULL,
[CustomRangeFrom] decimal (18, 2) NOT NULL,
[CustomRangeTo] decimal (18, 2) NOT NULL,
[CustomStringValue] nvarchar(max) NULL,
[ProductId] int NOT NULL,
[ProductPropertyId] int NOT NULL,
[ProductPropertyOptionId] int …
Run Code Online (Sandbox Code Playgroud) c# database-design entity-framework-core ef-core-2.0 entity-framework-migrations
方法和要求: 我们有一个使用 Sql Server 数据库在 ASP.Net Core 中开发的微服务架构,其中每个微服务都有自己的 SQL 数据库,并且不允许我们进行跨微服务通信来聚合数据并将数据从微服务发送回 api 网关和进一步回到 UI(浏览器)。
我们的浏览器有一个数据网格,需要从不同的微服务聚合数据后显示数据,例如一个数据网格必须显示客户姓名、地址、预订参考号。电话号码、国家/地区名称、酒店名称、酒店地址、酒店费用和其他更多详细信息。
上面的数据网格中还有一个功能,可以根据其中的每一列对上面的网格数据进行排序;根据不同的列值过滤网格也是一个要求。此外,我们还需要在同一网格中进行分页,页面大小为 10 条记录。
目前,据我所知,数据聚合必须发生在 API 网关层,并且在其之上必须应用排序、过滤和分页功能。
我们使用 EF Core 2.0 作为数据 ORM,将数据发送回微服务并进一步响应。
问题1:
哪一层(UI、API 网关、微服务)应该执行这种排序、过滤和分页功能,以便获得最佳性能和更好的用户体验?
问题2:
是否有可能所有参数(例如排序顺序、排序列名称、页面大小、页码、筛选列名称、筛选列值)都应始终从 API 网关层发送到微服务 api,并成功实现所有功能而没有任何延迟以及读取操作的最佳性能?
问题3:
我们创建一个粗粒度的微服务来代替上述选项,对数据进行聚合、排序、过滤和分页,而不是 API 网关层进行聚合(目前 API 网关仅在其他微服务中进行聚合),这是一个好的模式吗? ?
pagination microservices asp.net-core-webapi api-gateway ef-core-2.0
我使用 .net core 2.0 和 EF core 2.0 配置了 Net core API。它包含存储库模式架构。
现在,我尝试使用 EF 更改跟踪器为每个保存更改实现审核日志。
我的问题:每当我尝试添加编辑/修改端点的日志时,原始值和当前值保持不变,并且是新更新的值。所以这样我就无法跟踪修改或更改。
这是我的ApplicationContext文件,我在其中覆盖了保存调用。
public class ApplicationContext : DbContext
{
public ApplicationContext(DbContextOptions options) : base(options: options) { }
public DbSet<Item> Item { get; set; }
public DbSet<ChangeLog> ChangeLog { get; set; }
public override int SaveChanges()
{
var modifiedEntities = ChangeTracker.Entries();
foreach (var change in modifiedEntities)
{
var entityType = change.Entity.GetType().Name;
if (entityType == "LogItem")
continue;
if (change.State == EntityState.Modified)
{
foreach (var prop in …
Run Code Online (Sandbox Code Playgroud) 我在 ASP.NET Core 2.2 应用程序中收到此警告
警告:Microsoft.EntityFrameworkCore.Infrastruct[10402] 已创建 20 多个“IServiceProvider”实例供实体框架内部使用。这通常是由于将新的单例服务实例注入每个 DbContext 实例而引起的。例如,调用 UseLoggerFactory 每次都会传入一个新实例 - 有关更多详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=869049 。考虑检查对“DbContextOptionsBuilder”的调用,这可能需要构建新的服务提供程序。
花了一些时间后我发现它发生在startup.cs中。我正在使用 IdentityServer3 + OpenIDCnnection 进行身份验证。
用户成功登录后,客户端应用程序对用户进行授权,确保用户存在于客户端应用程序的数据库中。
客户端应用程序的Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IAccountService, AccountService>();
services.AddDbContext<Data.Entities.MyDBContext>(options =>
{
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
sqlServerOptions => sqlServerOptions.CommandTimeout(sqlCommandTimeout));
});
services.AddAuthentication(options =>
{
// removed for brevity purpose
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
// removed for brevity purpose
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Events = new OpenIdConnectEvents()
{
OnTokenValidated = async context =>
{
Data.Entities.UserAccount userAccount = …
Run Code Online (Sandbox Code Playgroud) 我试图在EntityFramework Core 2.0的SELECT查询中使用TransactionScope.但是我收到此错误:"不支持在Ambient事务中登记."
当我选择查询时,我们的想法是实现"NO LOCK"选项(我知道这个选项不是一个好主意,但它是供应商的要求).所以我添加了一个扩展方法(带有NOLOCK的实体框架)
public static async Task<List<T>> ToListReadUncommittedAsync<T>(this IQueryable<T> query)
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
}, TransactionScopeAsyncFlowOption.Enabled))
{
var result = await query.ToListAsync();
scope.Complete();
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
而且我也设置忽略环境交易警告.
public static void AddEntityFramework(this IServiceCollection services, string connectionString)
{
services.AddDbContextPool<OptomateContext>(options =>
{
options.UseSqlServer(connectionString);
options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
});
}
Run Code Online (Sandbox Code Playgroud)
我在我的存储库中有如下查询
public async Task<Patient> GetPatient(Common.Resources.Patient patient)
{
var pat = await Dbset.Where(x => string.Equals(x.Surname,patient.Surname,
StringComparison.CurrentCultureIgnoreCase)).ToListReadUncommittedAsync();
return pat.FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
我明白.Net Core …
c# entity-framework transactionscope entity-framework-core ef-core-2.0
我正在尝试在EF Core中实现一些在EF 6中非常适合我的东西.
我将List<T>
属性的内容序列化为DB中的Json字符串.<T>
可以是几乎任何东西,因为Json.Net负责序列化我们抛出的任何东西.我的集合公开了一个Json
字符串属性,并负责序列化/反序列化.
这种方法对于结构化嵌套数据来说是方便有效的,其中关系模型会带来不必要的开销和复杂性.
在EF 6中我会做这样的事情:
[ComplexType]
public class SelfSerializingCollection<T> : Collection<T>
{
public void AddRange(IEnumerable<T> collection)
{
foreach (var item in collection)
{
Add(item);
}
}
protected string Json
{
get { return JsonConvert.SerializeObject(this); }
private set
{
Clear();
if (value == null)
{
return;
}
AddRange(JsonConvert.DeserializeObject<T[]>(value));
}
}
}
Run Code Online (Sandbox Code Playgroud)
EF 6不支持映射泛型类型,因此我们为每种类型的List提供了我们可能需要的具体实现:
public class PhoneNumberCollection : SelfSerializingCollection<PhoneNumber> { }
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
public class Contact {
public PhoneNumberCollection PhoneNumbers { get; set; }
} …
Run Code Online (Sandbox Code Playgroud) 我通过以下方式在EF Core 2.0中调用存储过程.
private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
dynamic temp;
using (MyDbContext MyDbContext = new MyDbContext(_options))
{
MyDbContext.Database.OpenConnection();
DbCommand cmd = MyDbContext.Database.GetDbConnection().CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = storedProcedureName;
using (var reader = cmd.ExecuteReader())
{
temp = reader.Cast<Task<IEnumerable<TEntity>>>();
}
}
return await temp;
}
Run Code Online (Sandbox Code Playgroud)
我需要转换DbDataReader
为Task<IEnumerable<TEntity>>
.
但是在尝试扩展temp变量以查看其值时,我收到此错误.
读取器关闭时无效尝试调用FieldCount.
请参阅随附的屏幕截图.
c# entity-framework entity-framework-core asp.net-core ef-core-2.0
我搜索并搜索过,我相信我知道答案.但我要问,只是为了确保......
我一直在EF Core 2.0模型中创建自有类型,并且到目前为止已经完成了......怪癖.我当前的问题是创建一个索引,该索引包含来自另一个实体内的自有类型的一个或多个属性.
从本质上讲,据我所知,拥有的类型遇到的问题与尝试在导航属性上进行索引相同(而且,BTW,非常棒的作业MS选择异常文本,不会告诉您实际问题......).但是,使用导航属性,您可以使用字符串名称版本并引用shadow属性.我没有运气尝试使用自有类型 - 看起来EF并没有为它们创建"阴影属性".引用实际列名称错误,因为它不是模型上定义的属性名称(并且似乎确认我的"无阴影属性"); 并且nameof
不适用于子对象,并且可能会给出错误的名称.
所以我采用的方法是尽可能多地使用Fluent API创建索引,然后在迁移脚本中直接添加我需要的其他列.虽然它有效,但由于我希望显而易见的原因,这是次优的.
那我错过了什么?我真的想要使用自有类型,但是在迁移时给出了"重命名Vortex",现在我已经接近说"拧它",将它们拉出来,然后手动重新进行,如果没有其他的话理由不是为了避免与我的团队其他成员一起.显然这是一个相对较新的功能,但我很难理解为什么它会在它所处的状态下发布...
我想DbContext
在我的ActionFilter中间件中使用a .可能吗?
public class VerifyProfile : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
using (var context = new SamuraiDbContext())
{
var user = filterContext.HttpContext.User.Identity.Name;
if (context.Profiles.SingleOrDefaultAsync(p => p.IdentityName == user).Result == null)
{
filterContext.Result = new RedirectResult("~/admin/setup");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码using (var context = new SamuraiDbContext())
需要传递选项.我应该再次通过DbContextOptionsBuilder()
这里还是有其他办法吗?
我想[VerifyProfile]
在我的控制器方法中有属性.有可能吗?
c# asp.net-core-mvc asp.net-core asp.net-core-2.0 ef-core-2.0
ef-core-2.0 ×10
c# ×6
asp.net-core ×3
entity-framework-migrations ×2
api-gateway ×1
ef-core-2.1 ×1
ef-core-2.2 ×1
pagination ×1