我正在将我的.NET Framework(EF6)代码转移到ASP.NET Core(EF Core),我偶然发现了这个问题.这是一些示例代码:
在EF6中,我使用Include()和Select()进行预加载:
return _context.Post
.Include(p => p.PostAuthor.Select(pa => pa.Author).Select(a => a.Interests))
Run Code Online (Sandbox Code Playgroud)
PostAuthor是一个联结表,还有一个Junction表"AuthorInterest",我不需要参与EF6(Select直接进入a.Interests).
无论如何,我可以看到在EF7中这是重做的,这意味着我现在应该使用ThenInclude()来嵌套查询.然而...
return _context.Post
.Include(p => p.PostAuthor)
.ThenInclude(pa => pa.Select(pa2 => pa2.Author))
...etc
Run Code Online (Sandbox Code Playgroud)
由于Select()语句,上面的代码失败了.https://docs.efproject.net/en/latest/querying/related-data.html上的文档似乎表明我不需要它,我可以立即访问作者,但我在最后一个lambda中获得了ICollection显示,所以我显然需要Select().我在查询中进一步查看了多个联结表,但为了简单起见,我们只关注第一个.
我该如何工作?
entity-framework entity-framework-core asp.net-core-mvc asp.net-core
我有一个较旧的asp.net核心身份数据库,我想将一个新项目(一个web api)映射到它.
仅仅为了测试,我复制了Models文件夹,以及上一个项目中的ApplicationUser文件(ApplicationUser只是继承自IdentityUser,没有任何变化) - 首先执行DB似乎是一个坏主意.
我在ConfigureServices中注册了Identity(但我没有将它添加到管道中,因为我的唯一目的是使用UserStore)
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
Run Code Online (Sandbox Code Playgroud)
我的期望是现在
UserManager<ApplicationUser>
Run Code Online (Sandbox Code Playgroud)
...应该自动注入构造函数.
但是,将以下代码添加到控制器私有UserManager _userManager时;
public UserController(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)
...每次调用api都会以异常结束:HttpRequestException:响应状态代码不表示成功:500(内部服务器错误).
删除"注入"代码可以顺利运行可以接受请求的web api.
在我的任何代码到达之前发生这种情况很难调试.知道为什么会这样吗?
PS从异常设置窗口启用所有异常后我得到了这个:
抛出异常:
Microsoft.Extensions.DependencyInjection.dll中的"System.InvalidOperationException"附加信息:尝试激活'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`4 [Namespace.Models]时,无法解析类型'Namespace.Data.ApplicationDbContext'的服务.ApplicationUser,Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole,Namespace.Data.ApplicationDbContext,System.String]".
c# asp.net-web-api asp.net-identity asp.net-core-mvc asp.net-core
我有一个巨大的json格式的"扁平"对象列表,以及一个有点复杂的关系数据库模式(大约有20个表对应于展平对象).我正在尝试在新的关系数据库中自动插入那些展平的对象:
foreach (var flattenedObject in flattenedObjects)
{
_repository.Insert(flattenedObject).Wait();
//some time logging, etc
}
Run Code Online (Sandbox Code Playgroud)
该Insert()方法调用AddRangeAsync(),并AddAsync()为一些在不同的表相关的对象.
由于扁平化对象是遗留的,我会说它们中约有0.001%是格式错误并且会违反数据库约束 - 例如尝试在其中一个表中插入重复的复合主键.
我期待这些罕见的错误,因此我的想法是 - 将整个Insert()操作包装在一个事务中 - 如果任何操作部分无效,只是不插入任何内容并记录错误,所以我可以再次尝试之前手动修改展平对象.因此我的代码看起来有点类似于:
public async Task Insert(FlattenedObject fo)
{
using (var transaction = _context.Database.BeginTransaction())
{
try
{
//magical code that calls AddAsync for multiple tables
}
catch (Exception ex)
{
transaction.Rollback()
//logging
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我的try块中某处发生错误(我尝试插入违反复合主键的对象),我的整个上下文对象就会变坏.
导致异常的对象仍然保留在我的DbContext中,并且AddAsync()在另一个事务中的任何后续调用都会触发新的异常.
我尝试为foreach上面的循环中的每个新对象重新创建我的DbContext和repo - 但即使这样,如果我查询:
_context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged);
Run Code Online (Sandbox Code Playgroud)
我看到我的旧对象仍然在dbContext的新实例中.
是否有任何(优雅)方式告诉我的上下文重置所有挂起的更改 - 以便每当发生错误时我都可以将它放在catch块中?我希望在失败的交易中发生的一切都留在那里而不是泄漏.
我不确定这是否与akka.net或TPL有关,但我会用演员来说明这个问题.
问题简而言之:有没有办法告诉akka.net一次触发更多线程而不是实际拥有CPU内核?这是示例代码和详细信息:
我目前正在使用配备8核处理器的笔记本电脑.所以我要说我创造了20个演员:
for (int i = 0; i < 20; i++)
{
actorList.Add(system.ActorOf<ExampleActor>());
}
Run Code Online (Sandbox Code Playgroud)
然后我将消息传递给所有这些:
actorList[0].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 1\t" + DateTime.Now.TimeOfDay);
actorList[1].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 2\t" + DateTime.Now.TimeOfDay);
...
actorList[19].Tell(new ExampleMessage());
Console.WriteLine("sent message to actor 20\t" + DateTime.Now.TimeOfDay);
Run Code Online (Sandbox Code Playgroud)
所有演员都这样做,而接收消息的是以下假的长时间运行过程:
Console.WriteLine("Accessing slow service\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(60000);
Console.WriteLine("Service call was successful\t" + DateTime.Now.TimeOfDay
+ "\t" + Thread.CurrentThread.ManagedThreadId);
Run Code Online (Sandbox Code Playgroud)
我在构造函数中也有这个代码,所以我知道实际创建actor的时间:
public ExampleActor()
{
Console.WriteLine("Creating " + this.Self.Path + DateTime.Now.TimeOfDay);
....
}
Run Code Online (Sandbox Code Playgroud)
所以现在当我运行应用程序时,我首先得到所有20个演员的"发送消息给演员"行 - …
我正在测试IdentityServer4,浏览文档以了解有关OAuth2,OpenId Connect和基于声明的身份验证的更多信息,所有这些都是我的新手.但是,一些示例代码表现得很奇怪,我无法弄清楚为什么......
因此,根据我的理解,当获得访问用户数据的权限时,客户端可以访问UserInfo端点,其包含诸如声明等的数据.
在IdentityServer4中甚至还有一个设置
GetClaimsFromUserInfoEndpoint
Run Code Online (Sandbox Code Playgroud)
文档建议我们将其设置为true.
所以我遵循IdentityServer4启动指南,一切都运行良好,直到一个点.本快速入门包含提供的示例代码,虽然我假设我遗漏了一些明显的东西并且看不到代码.
基于正在运行的服务器的openId Configuration页面,userinfo端点位于 http:// localhost:5000/connect/userinfo,当我尝试通过浏览器访问它时,我看到一个声称我已记录的导航栏在,但页面的主体是一个登录提示.看起来很奇怪,但我假设这是因为我登录localhost:5000(IdentityServer4),但我没有发送我在localhost:5002上为客户端获取的userId令牌.
所以我在我的客户端应用程序上编写了以下代码:
public async Task<IActionResult> GetData()
{
var accessToken = HttpContext.Authentication.GetTokenAsync("access_token").Result;
HttpClient client = new HttpClient();
client.SetBearerToken(accessToken);
var userInfo = await client.GetStringAsync("http://localhost:5000/connect/userinfo");
return Content(userInfo);
}
Run Code Online (Sandbox Code Playgroud)
在这里,我知道GetTokenAsync("access_token")应该像连接到API的客户端应用程序在示例项目中的其他位置一样使用.但是,我得到的响应再次是IdentityServer的布局页面和登录提示.
知道我的错误是什么以及如何访问UserInfo端点?
编辑:删除线程阻塞,这样我就不会向陌生人展示可耻的测试代码
好的,事实证明这个代码应该有一个简化的版本,即:
UserInfoClient uic = new UserInfoClient("http://localhost:5000", idToken);
var result = await uic.GetAsync();
return Content(JsonConvert.SerializeObject(result.Claims));
Run Code Online (Sandbox Code Playgroud)
然而,问题仍然存在,即使UserInfoClient中的封装代码也会遇到"无用户端点数据,只是示例网站的布局"的问题.
看完有关OAuth2的大量教程之后,有一种最佳实践,每个人都反复声明-如果您有React应用(或Angular或Ember),则必须对其使用隐式流。
我了解将客户端凭据存储在公开可见的javascript中不起作用。但是,我的情况有些不同:
为了更好地理解为什么这是我想出的原因,以下是我收到的一些可能不常见的要求:
我无法确定为什么这个想法会那么糟糕。是否有任何技术问题可能会阻止此工作?还是存在安全风险?
single-sign-on oauth-2.0 openid-connect microservices identityserver4
我正在尝试使用 Typeahead/Bloodhound 进行建议和搜索。为简单起见,让我们假设我有两种类型的模型对象 - Country和City。
public class Country
{
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
(服务器端在 ASP.NET 中,但这与问题无关)。
City 实际上与 Country 相同,只是名称不同。
无论如何,在造型之前,我希望最终结果如下所示:
(如果不明显,我在文本框中写了“AL”,其余字母构成第一个建议)
我可以通过使用多个 Bloodhounds 轻松实现这一点:
var countries = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/countries/%QUERY',
wildcard: '%QUERY'
}
});
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
limit: 5,
remote: {
url: 'http://localhost:5000/api/cities/%QUERY',
wildcard: '%QUERY'
}
});
Run Code Online (Sandbox Code Playgroud)
和多个输入对象预先输入:
$('#remote .typeahead').typeahead(null,
{
name: 'countries',
display: 'name',
source: countries, …Run Code Online (Sandbox Code Playgroud) asp.net-core ×3
c# ×3
.net ×1
akka.net ×1
bloodhound ×1
javascript ×1
json ×1
oauth-2.0 ×1
typeahead.js ×1