Repository / UnitOfWork Add throws无法将值NULL插入列错误

时间:2015-04-24 03:45:27

标签: c# .net entity-framework repository-pattern n-tier-architecture

我正在开发一个从REST API获取数据的应用程序。我正在针对一个具体的类解析json,然后逐步将该段转换为UpdateInsert(取决于该行是否存在)到SQL数据库中。其中一部分是创建一个唯一标识符列,其中包含SkillIdAccountId,恰当地命名为AccountSkillId。我相信我已将此问题追溯到我Add的{​​{1}}部分,因为Repository有效,但Commit没有。

Add的行为就像我传递的实体是空的,但是当我在本地看它时它表明它不是空的:

Screenshot

以下是我的业务层中的代码尝试

Add

以下是我的Repository Abstract Class

    public void GetSkills()
    {
        var dataContext = new LivePersonContext(ConfigurationWrapper.DataConnectionString);
        var apiRequest = new OAuthRequest();
        var builder = new StringBuilder("");

        using (dataContext)
        {
            var uow = new UnitOfWork(dataContext);
            var accountCredentialIds = uow.Accounts.GetAll().Select(c => c.AccountID).ToList();

            foreach (var a in accountCredentialIds)
            {
                var account = a;
                try
                {
                    builder.Clear();
                    var consumerKey = uow.Accounts.GetById(account).ConsumerKey;
                    var consumerSecret = uow.Accounts.GetById(account).ConsumerSecret;
                    var token = uow.Accounts.GetById(account).Token;
                    var tokenSecret = uow.Accounts.GetById(account).TokenSecret;
                    builder.AppendFormat(ConfigurationWrapper.SkillsUri, account);
                    var uri = builder.ToString();

                    var response = apiRequest.OauthRequestResponse(uri, consumerKey, consumerSecret, token,
                        tokenSecret);
                    if (response != null)
                    {
                        using (var reader = new StreamReader(response.GetResponseStream()))
                        {
                            var json = reader.ReadToEnd();
                            var jsonObj = JsonConvert.DeserializeObject<List<Entity.Skills>>(json);

                            var currentSkillData = uow.SkillMeta.GetAll().Select(c => c.AccountSkillId).ToList();

                            foreach (var item in jsonObj)
                            {
                                if (item.id != null)
                                {
                                    var itemId = int.Parse(item.id);
                                    var string2 = item.id + account;


                                    var accountSkillId = int.Parse(string2);

                                    if (currentSkillData.Contains(accountSkillId))
                                    {
                                        var skillUpdate = uow.SkillMeta.GetById(accountSkillId);

                                       // skillUpdate.AccountSkillID = int.Parse(accountSkillId);
                                        //skillUpdate.AccountID = account;
                                        //skillUpdate.SkillID = int.Parse(item.id);
                                        skillUpdate.Name = item.name;
                                        skillUpdate.IsDefault = item.isDefault;
                                        skillUpdate.Description = item.description;
                                        uow.Commit();
                                    }
                                    else
                                    {
                                        var addSkill = new lp_Skill_Meta
                                        {
                                            AccountSkillId = accountSkillId,
                                            AccountId = account,
                                            SkillId = itemId,
                                            Name = item.name,
                                            IsDefault = item.isDefault,
                                            Description = item.description,

                                            //TODO: Verify that they are only ever passing single values
                                            Rel = item.links[0].rel,
                                            Href = item.links[0].href
                                        };


                                            uow.SkillMeta.Add(addSkill);
                                            uow.Commit();
                                        }
                                }
                            }
                        }
                    }
                }
                catch (Exception exception)
                {
                    var lEngine = new LoggerEngine{Logger = _logger};
                    lEngine.Log("ERROR: " + exception);
                }
            }
        }
    }

public abstract class Repository<T> : IRepository<T> where T : class { protected DbSet<T> _objectSet; public Repository(BaseContext context) { _objectSet = context.Set<T>(); } #region IRepository<T> Members public abstract T GetById(object id); public IEnumerable<T> GetAll() { return _objectSet; } public IEnumerable<T> Query(Expression<Func<T, bool>> filter) { return _objectSet.Where(filter); } public void Add(T entity) { _objectSet.Add(entity); } public void Remove(T entity) { _objectSet.Remove(entity); } #endregion } 是我的DAL中的BaseContext抽象

这是我想要添加到我的数据库中的实体

DbContext

以下是数据库的架构:

public class lp_Skill_Meta
{
    [Key]  
    public long AccountSkillId { get; set; }

    public int AccountId { get; set; }
    public int SkillId { get; set; }
    public string Name { get; set; }
    public bool IsDefault { get; set; }
    public string Description { get; set; }
    public string Rel { get; set; }
    public string Href { get; set; }
}

正如您在图片中看到的那样,当我将实体传递给add并尝试提交更改时,实体不为空。但我仍然得到:

  

无法将值NULL插入列CREATE TABLE [dbo].[lp_Skill_Meta]( [AccountSkillId] [bigint] NOT NULL, [AccountId] [int] NOT NULL, [SkillId] [int] NOT NULL, [Name] [varchar](250) NULL, [IsDefault] [bit] NULL, [Description] [varchar](max) NULL, [Rel] [varchar](50) NULL, [Href] [varchar](250) NULL ) ON [PRIMARY] ,表中   `DatabaseName.dbo.lp_Skill_Meta&#39 ;;列不允许空值。插入   失败。\ r \ n声明已经终止。

我现在已经盯着这几个小时了,并且一直在搜索和搜索,并没有看到这种情况(不是说它不在那里),但任何帮助都会令人惊讶。

更新:根据以下评论中的SQL Trace帽子提示,以下是EF正在尝试运行的查询

  

exec sp_executesql N&#39; INSERT [dbo]。[lp_Skill]([AccountId],[SkillId],   [Name],[IsDefault],[Description],[Rel],[Href])VALUES(@ 0,@ 1,@ 2,   @ 3,@ 4,@ 5,@ 6)SELECT [AccountSkillId] FROM [dbo]。[lp_Skill] WHERE   @@ ROWCOUNT&gt; 0 AND [AccountSkillId] = scope_identity()&#39; ,N&#39; @ 0 int,@ 1   int,@ 2 nvarchar(max),@ 3 bit,@ 4 nvarchar(max),@ 5 nvarchar(max),@ 6   nvarchar(max)&#39;   ,@ 0 = 10740014,@ 1 = 6,@ 2 = N&#39;滥用者&#39;,@ 3 = 0,@ 4 = N&#39;滥用者&#39;,@ 5 = N&#39;自&#39 ;,@ 6 = N&#39; https://sales.liveperson.net/api/account/10740014/skills/6&#39;

AccountSkillId不是DB中的标识列,所以这就是为什么它抛出NULL。现在开始搜索如何让它停止将该列标记为标识...

1 个答案:

答案 0 :(得分:3)

根据这个问题:Cannot insert the value NULL into column in ASP.NET MVC Entity Framework

答案归结为将[DatabaseGenerated(DatabaseGeneratedOption.None)]添加到我的实体运行中,就像一个魅力。巨大的呼喊@JeffTreuting指出我使用SQL Trace正确的方向。老实说,我甚至都没想过。再次感谢大家!

    public class lp_Skill
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long AccountSkillId { get; set; }

    public int AccountId { get; set; }
    public int SkillId { get; set; }
    public string Name { get; set; }
    public bool IsDefault { get; set; }
    public string Description { get; set; }
    public string Rel { get; set; }
    public string Href { get; set; }
}