小编nik*_*ovn的帖子

在连接表上使用EF Core ThenInclude()

我正在将我的.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

28
推荐指数
1
解决办法
2万
查看次数

ASP.NET Core Identity不会注入UserManager <ApplicationUser>

我有一个较旧的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

9
推荐指数
2
解决办法
2万
查看次数

如何在EF 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块中?我希望在失败的交易中发生的一切都留在那里而不是泄漏.

.net c# entity-framework entity-framework-core

8
推荐指数
2
解决办法
4830
查看次数

在akka.net中立即触发多个线程

我不确定这是否与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个演员的"发送消息给演员"行 - …

c# task-parallel-library akka.net

5
推荐指数
1
解决办法
1221
查看次数

无法从Client访问IdentityServer4 doc示例中的UserInfo端点

我正在测试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中的封装代码也会遇到"无用户端点数据,只是示例网站的布局"的问题.

openid-connect asp.net-core identityserver4

5
推荐指数
1
解决办法
2403
查看次数

如果我有服务器端代理,可以将Oauth2授权代码流用于SPA(React应用)吗?

看完有关OAuth2的大量教程之后,有一种最佳实践,每个人都反复声明-如果您有React应用(或Angular或Ember),则必须对其使用隐式流

我了解将客户端凭据存储在公开可见的javascript中不起作用。但是,我的情况有些不同:

  1. 我仅将Oauth2用于微服务的单点登录和令牌生成。我选择它而不是简单地生成令牌,因为受支持的第三方库是围绕Oauth2想法构建的。
  2. 我的想法是拥有一个React应用程序和一个ASP.NET MVC应用程序,该应用程序可以处理JavaScript并充当API请求的代理。用户通过使用Oauth2授权代码流对服务器端应用程序进行身份验证。
  3. 然后,如果需要从API检索数据,可以从React调用我的ASP.NET MVC应用程序(通过发送一个简单的cookie)。MVC应用程序保留令牌,而不会将其暴露给用户的浏览器。
  4. 显然,当被调用时,我的MVC应用程序会将请求重定向到必要的API,并提供承载令牌。

为了更好地理解为什么这是我想出的原因,以下是我收到的一些可能不常见的要求:

  1. 我真的不希望共享访问令牌-即使访问令牌的寿命相对较短。
  2. 我还希望能够将每个用户帐户限制为3个并发用户会话。使用cookie和服务器端会话很容易做到。

我无法确定为什么这个想法会那么糟糕。是否有任何技术问题可能会阻止此工作?还是存在安全风险?

single-sign-on oauth-2.0 openid-connect microservices identityserver4

4
推荐指数
1
解决办法
2650
查看次数

如何通过 Typeahead 和 Bloodhound 一次性使用多个数据集?

我正在尝试使用 Typeahead/Bloodhound 进行建议和搜索。为简单起见,让我们假设我有两种类型的模型对象 - CountryCity

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)

javascript json typeahead.js bloodhound

2
推荐指数
1
解决办法
2642
查看次数