Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用实体框架将不同的记录插入带有外键的表中_C#_Asp.net_Entity Framework_Asp.net Web Api - Fatal编程技术网

C# 使用实体框架将不同的记录插入带有外键的表中

C# 使用实体框架将不同的记录插入带有外键的表中,c#,asp.net,entity-framework,asp.net-web-api,C#,Asp.net,Entity Framework,Asp.net Web Api,这些是我的模型,我使用实体框架,采用代码优先的方法 public class Respondent { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int RespondentId { get; set; } public User Requester { get; set; } public User Provider { get; set; }

这些是我的模型,我使用实体框架,采用代码优先的方法

public class Respondent
{
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int RespondentId { get; set; }
        public User Requester { get; set; }

        public User Provider { get; set; }
        public string Role { get; set; }
}

public class User: IUser
{
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int UserId { get; set; }
        public int UPI { get; set; }
        public string Name { get; set; }
}
这是两个生成表之间的关系

我想要的是,若用户表中存在用户,那个么不要创建另一个用户条目

问题是当我添加一个新的提供者(类型为user)时,每次它在user中创建一个新条目时,即使该用户存在;我想要的是在表中添加该用户的引用

private Context db = new Context();

public async Task<IHttpActionResult> PostRespondent(Respondent respondent)
{
        var TempProvidersList = respondent.Providers.ToList();

        try
        {
            var requester = db.Users.Single(s => s.UserId == respondent.Requester.UserId);
            requester.IsPublic = false;
            var providerIds = respondent.Providers.Select(x => x.UPI).ToList();

            foreach (var providerId in providerIds)
            {
                if (!db.Respondents.Any(x => x.Requester.UserId == requester.UserId && x.Provider.UPI == providerId))
                {
                    var provider = respondent.Providers.Single(x => x.UPI == providerId);
                    provider.IsPublic = true;

                    db.Respondents.Add(new Respondent() { Requester = requester, Provider = provider, Role = provider.Role });
                }
            }

            db.SaveChanges();
        }
        catch (Exception ex)
        {
        }

        return CreatedAtRoute("DefaultApi", new { id = respondent.RespondentId }, respondent);
}
private Context db=new Context();
公共异步任务后响应者(响应者-响应者)
{
var TempProvidersList=响应者.Providers.ToList();
尝试
{
var requester=db.Users.Single(s=>s.UserId==responder.requester.UserId);
requester.IsPublic=false;
var providerIds=appender.Providers.Select(x=>x.UPI.ToList();
foreach(providerId中的变量providerId)
{
if(!db.responders.Any(x=>x.Requester.UserId==Requester.UserId&&x.Provider.UPI==providerId))
{
var provider=响应者.Providers.Single(x=>x.UPI==providerId);
provider.IsPublic=true;
添加(新的响应者(){Requester=Requester,Provider=Provider,Role=Provider.Role});
}
}
db.SaveChanges();
}
捕获(例外情况除外)
{
}
返回CreatedAtRoute(“DefaultApi”,新的{id=respondent.RespondentId},respondent);
}

我认为问题在于传递由不同DbContext加载的实体,然后在新的DbContext中添加对这些实体的引用

这里的代码没有多大意义:

var res = db.Respondents
    .Include(user => user.Requester)
    .Include(user => user.Provider)
    .Where(o => o.Requester.UserId == requester.UserId ).ToList();
代码中任何地方都不使用“res”。你用的是“a”吗?我想是同一个词? 首先,如果您只想检查是否存在行,请使用
Any()

而不是加载所有可用的实体,只是为了检查是否存在某些实体

我看到的问题是:

tempProvider = TempProvidersList[i];
db.Respondents.Add(new Respondent() { Requester = requester, Provider = tempProvider, Role = TempProvidersList[i].Role });
这是将新响应中的提供者引用设置为可能从其他DbContext实例加载的用户(提供者)

要解决此问题,应从当前DbContext加载您设置的任何引用:

var providerIds = respondent.Providers.Select(x => x.UPI).ToList();
var providers = db.Users.Where(x => providerIds.Contains(x.UPI)).ToList();

var requester = db.Users.Single(s => s.UserId == respondent.Requester.UserId);
requester.IsPublic = false;
foreach(var providerId in providerIds)
{
   if (!db.Respondents.Any(x => x.Requester.UserId == requester.UserId)) 
   {
       var provider = providers.Single(x => x.UPI == providerId);
       provider.IsPublic = true;

       db.Respondents.Add(new Respondent() { Requester = requester, Provider = provider, Role = provider.Role });
   }
}
db.SaveChanges();
我选择根据ID一次加载所有适用的提供者,而不是在循环中一次加载一个提供者。在循环中,我只是尝试从加载的集合中检索与ID匹配的那个

我会用try/catch块包装它并处理异常。可能出现的例外情况是,找不到ProviderId的用户。(可以删除用户吗?)我对ID而不是加载的引用进行了foreach,因为基于上述条件,该集合可能没有针对每个ID的实体。(如果6个ID中只有5个加载提供者用户,则ID集合将有6个元素,但实体集合将只有5个)


这里的另一点是使用
Single
而不是
FirstOrDefault
,在这里您需要一条记录。这将强制执行该规则,如果存在多个或没有匹配的记录,则将引发异常。只有在预期结果是找不到行时,才应使用“OrDefault”变量
FirstOrDefault
将在多个匹配项进入数据库时隐藏问题,如果没有“OrderBy”子句,则无法依赖将返回哪个引用。

我认为问题是由于传递由不同DbContext加载的实体,然后在新的DbContext中添加对这些实体的引用

这里的代码没有多大意义:

var res = db.Respondents
    .Include(user => user.Requester)
    .Include(user => user.Provider)
    .Where(o => o.Requester.UserId == requester.UserId ).ToList();
代码中任何地方都不使用“res”。你用的是“a”吗?我想是同一个词? 首先,如果您只想检查是否存在行,请使用
Any()

而不是加载所有可用的实体,只是为了检查是否存在某些实体

我看到的问题是:

tempProvider = TempProvidersList[i];
db.Respondents.Add(new Respondent() { Requester = requester, Provider = tempProvider, Role = TempProvidersList[i].Role });
这是将新响应中的提供者引用设置为可能从其他DbContext实例加载的用户(提供者)

要解决此问题,应从当前DbContext加载您设置的任何引用:

var providerIds = respondent.Providers.Select(x => x.UPI).ToList();
var providers = db.Users.Where(x => providerIds.Contains(x.UPI)).ToList();

var requester = db.Users.Single(s => s.UserId == respondent.Requester.UserId);
requester.IsPublic = false;
foreach(var providerId in providerIds)
{
   if (!db.Respondents.Any(x => x.Requester.UserId == requester.UserId)) 
   {
       var provider = providers.Single(x => x.UPI == providerId);
       provider.IsPublic = true;

       db.Respondents.Add(new Respondent() { Requester = requester, Provider = provider, Role = provider.Role });
   }
}
db.SaveChanges();
我选择根据ID一次加载所有适用的提供者,而不是在循环中一次加载一个提供者。在循环中,我只是尝试从加载的集合中检索与ID匹配的那个

我会用try/catch块包装它并处理异常。可能出现的例外情况是,找不到ProviderId的用户。(可以删除用户吗?)我对ID而不是加载的引用进行了foreach,因为基于上述条件,该集合可能没有针对每个ID的实体。(如果6个ID中只有5个加载提供者用户,则ID集合将有6个元素,但实体集合将只有5个)


这里的另一点是使用
Single
而不是
FirstOrDefault
,在这里您需要一条记录。这将强制执行该规则,如果存在多个或没有匹配的记录,则将引发异常。只有在预期结果是找不到行时,才应使用“OrDefault”变量
FirstOrDefault
将隐藏多个匹配项进入DB的问题,如果没有“OrderBy”子句,您无法依赖将返回的引用。

“响应者”来自客户。就EF而言,它是一个POCO类,而不是一个跟踪实体。引用“TempProvidersList”中的任何实体或其相关类将被视为全新实体,从而插入重复项。这就是为什么在客户机和服务器之间传递实体是个坏主意的例子。在你的方法中尝试上面的代码,看看是否仍然有重复的代码。你能将当前代码作为编辑附加到原始问题中吗?
var provider=append.Providers.Sin