C#ASP.Net - 尝试从表中删除数据时出错

时间:2017-08-29 11:19:03

标签: c# asp.net sql-server entity-framework

我有表Player和表统计信息以及其他在此问题中不重要的表。 Table Player具有PK Player_ID,表Statistic中为FK。这些表之间的关系是一对多的(一个玩家可以有更多的统计数据)。

这是代码: GenericRepository(我已创建它以具有CRUD方法的唯一类)

public async Task<int> Delete<T>(Guid id) where T : class
{
        try
        {
            T entity = await Get<T>(id);
            Context.Set<T>().Remove(entity);
            return await Context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            throw ex;
        }
}

PlayerRepository(用于管理Player表上的操作)

public async Task<int> Delete(Guid id)
{
        try
        {
            var player = await GenRepository.Get<Player>(id);
            if (player == null)
            {
                return 404;
            }
            else
            {
                return await GenRepository.Delete(player);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
}

PlayerService(WebAPI中存储库和控制器之间的连接)

public async Task<int> Delete(Guid id)
{
        try
        {
            return await PlayerRepository.Delete(id);
        }
        catch (Exception ex)
        {
            throw ex;
        }
}

的PlayerController

[HttpDelete]
    [Route("deleteplayer")]
    public async Task<HttpResponseMessage> Delete(Guid id)
    {
        try
        {
            var Finder = Mapper.Map<PlayerView>(await PlayerService.Get(id));
            if(Finder == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Player doesn't exist in database.");
            }

            var Response = await PlayerService.Delete(id);
            var profile = "../../../app/pictures/FootballFanAppPictures/" + Finder.Club_ID.ToString().ToUpper() + "/profiles/" + id.ToString().ToUpper() + ".png";
            var details = "../../../app/pictures/FootballFanAppPictures/" + Finder.Club_ID.ToString().ToUpper() + "/" + id.ToString().ToUpper() + ".png";
            if (System.IO.File.Exists(profile))
            {
                System.IO.File.Delete(profile);
            }
            if (System.IO.File.Exists(details))
            {
                System.IO.File.Delete(details);
            }
            return Request.CreateResponse(HttpStatusCode.OK, Response);
        }
        catch(Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
        }
    }

实体模型:

- 数据库模型

 public partial class Player
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Player()
    {
        this.Statistic = new HashSet<Statistic>();
    }

    public System.Guid Player_ID { get; set; }
    public System.Guid Club_ID { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public double Height { get; set; }
    public int Weight { get; set; }
    public System.DateTime BirthDate { get; set; }
    public string Nationality { get; set; }
    public string Position { get; set; }
    public int Shirtnmbr { get; set; }

    public virtual Club Club { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Statistic> Statistic { get; set; }
}
using System;
using System.Collections.Generic;

public partial class Statistic
{
    public System.Guid Statistic_ID { get; set; }
    public System.Guid Player_ID { get; set; }
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int FoulsFor { get; set; }
    public int FoulsAgainst { get; set; }
    public int ShotsTotal { get; set; }
    public int ShotsGoal { get; set; }

    public virtual Player Player { get; set; }
}

-domain models(在存储库中使用)

public class PlayerDomain : IPlayerDomain
{
    public Guid Player_ID { get; set; }
    public Guid Club_ID { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public double Height { get; set; }
    public int Weight { get; set; }
    public DateTime BirthDate { get; set; }
    public string Nationality { get; set; }
    public string Position { get; set; }
    public int Shirtnmbr { get; set; }
    public virtual ICollection<IStatisticDomain> Statistic { get; set; }
}
public class StatisticDomain: IStatisticDomain
{
    public Guid Statistic_ID { get; set; }
    public Guid Player_ID { get; set; }
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int FoulsFor { get; set; }
    public int FoulsAgainst { get; set; }
    public int ShotsTotal { get; set; }
    public int ShotsGoal { get; set; }
}

-view models(在控制器中使用)

public class PlayerView
{
    public Guid Player_ID { get; set; }
    public Guid Club_ID { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public double Height { get; set; }
    public int Weight { get; set; }
    public DateTime BirthDate { get; set; }
    public string Nationality { get; set; }
    public string Position { get; set; }
    public int Shirtnmbr { get; set; }
    public virtual ICollection<StatisticView> Statistic { get; set; }
}
public class StatisticView
{
    public Guid Statistic_ID { get; set; }
    public Guid Player_ID { get; set; }
    public int Goals { get; set; }
    public int Assists { get; set; }
    public int FoulsFor { get; set; }
    public int FoulsAgainst { get; set; }
    public int ShotsTotal { get; set; }
    public int ShotsGoal { get; set; }
}

每个班级都在一个单独的文件中。我使用数据库第一种方法,所以我得到.edmx文件和数据库模型。数据库在SQL Server Management Studio中创建。

我可以更新播放器,但是当我尝试删除它时,我收到此错误:

  

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

我在google和stackoverflow上搜索了各种答案,但我找不到解决问题的答案

3 个答案:

答案 0 :(得分:0)

我没有在代码中看到删除播放器上的统计信息删除。 在删除播放器之前,您需要先删除所有与播放器相关的统计信息。如果剩下任何一个,玩家将在删除操作时失败。

答案 1 :(得分:0)

在致电此行之前:

var Response = await PlayerService.Delete(id);

您需要检索分配给您要删除的播放器的统计信息列表。

然后循环遍历每个统计信息并首先从数据库中删除它们。

var stats = Finder.Statistic.ToList();

if(stats != null && stats.Any())
{
   foreach(var stat in stats)
   { 
      //retrieve your stat record here from the database
      //check that the stat record is not null
      //delete your stat record here
   }
}

然后您应该可以删除您的播放器记录,因为不再有对它的引用。

OR

你可以将ON DELETE CASCADE设置为true,但是你必须要小心,你完全理解在删除玩家时将删除所有内容。

答案 2 :(得分:0)

设置PrimaryKey和Foreignkey关系:根据@Bad Dub建议。

enter image description here