【问题标题】:Database operation expected to affect 1 row(s) but actually affected 0 row(s) with entity framework数据库操作预计会影响 1 行,但实际上影响了实体框架的 0 行
【发布时间】:2019-10-25 11:45:39
【问题描述】:

我有下表:

我有以下触发器:

CREATE TRIGGER check_insertion_to_pushes_table
    BEFORE INSERT
    ON "Pushes"
    FOR EACH ROW
EXECUTE PROCEDURE trg_insert_failed_push();

CREATE or replace FUNCTION trg_insert_failed_push()
    RETURNS trigger AS
$func$
BEGIN
    IF (NEW."Sent" = false) THEN
        IF EXISTS(
                SELECT *
                FROM "Pushes"
                where "Sent" = false
                  and "CustomerId" = NEW."CustomerId"
                  and "PushTemplateId" = NEW."PushTemplateId"
            )
        THEN
            RETURN NULL;
        END IF;
        RETURN NEW;
    ELSE
        RETURN NEW;
    end if;
END
$func$ LANGUAGE plpgsql;

如果数据库中有CustomerIdPushTemplateIdSent 等于新行且Sent 为假的行,我想通过插入。

我有以下测试来检查它是如何工作的:

    public class Tests
    {
        private IPushRepository _pushRepository;
        [NUnit.Framework.SetUp]
        public void Setup()
        {
            var confBuilder = new ConfigurationBuilder();
            var configuration = confBuilder.AddJsonFile("/home/aleksej/projects/makeapppushernet/TestProject/appsettings.LocalToProdDb.json").Build();
            _pushRepository = new PushRepository(new ApplicationDbContext(configuration));

        }

        [Test]
        public async Task Test1()
        {
            var push = new Push
            {
                CustomerId = 69164,
                Sent =  false,
                PackageId = "com.kek.lol",
                Category = "betting",
                Advertiser = "Advertiser",
                TemplateType = "opened_and_not_registration",
                IntervalType = "minutes",
                BottomDateTimeBorder =  90,
                TopDateTimeBorder = 60,
                ClientStartDateTime = DateTime.Now,
                FCMResponse = "hello",
                CreatedAt = DateTime.Now,
                LangCode = "En",
                PushBody = "Hello",
                PushTitle = "Hello",
                PushTemplateId = 15 
            };

            var pushesList = new List<Push>
            {
                push
            };

            await _pushRepository.SaveAsync(pushesList);

            Assert.Pass();
        }
    }

如果我在测试中将false 设置为Sent,则会出现以下异常:

数据库操作预计会影响 1 行,但实际上会影响 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=527962

如果我设置true 我什么都没有。它只是通过插入。

更新

好的,在 Shay Rojansky 的回答的帮助下,我有以下触发代码:

CREATE TRIGGER check_insertion_to_failed_pushes_table
    BEFORE INSERT
    ON "FailedPushes"
    FOR EACH ROW
EXECUTE PROCEDURE trg_insert_failed_push();

CREATE or replace FUNCTION trg_insert_failed_push()
    RETURNS trigger AS
$func$
DECLARE
    push        "FailedPushes"%ROWTYPE;
    old_push_id numeric;
BEGIN
    old_push_id = (SELECT "FailedPushId"
                   FROM "FailedPushes"
                   where "CustomerId" = NEW."CustomerId"
                     and "PushTemplateId" = NEW."PushTemplateId");
    push := new;

    IF (old_push_id != 0)
    THEN
        push."FailedPushId" = old_push_id;

        DELETE
        FROM "FailedPushes"
        where "CustomerId" = NEW."CustomerId"
          and "PushTemplateId" = NEW."PushTemplateId";

        return push;
    END IF;

    push."FailedPushId" = (SELECT count(*) FROM "FailedPushes")::numeric + 1;

    return push;
END
$func$ LANGUAGE plpgsql;

也许不是很优雅,但它确实有效。

【问题讨论】:

    标签: postgresql entity-framework-core npgsql


    【解决方案1】:

    您实际上是在将 PostgreSQL 配置为在某些条件下忽略 INSERT,但 EF Core 并没有以任何方式意识到这一点。当您告诉 EF Core 添加新行时,它希望这会在数据库中实际发生。如果实体具有任何数据库生成的列(标识、序列),EF Core 还希望接收新插入行的值(并将它们填充回实体的 CLR 实例)。

    所以 AFAIK 你不能只是告诉数据库忽略 INSERT 并期望一切正常......

    请参阅this issue 了解 EF Core upsert 支持,这有点相关。

    【讨论】:

    • 您一次又一次地帮助我,谢谢!在您指定的 GitHub 链接中,我找到了这个库 github.com/artiomchi/FlexLabs.Upsert。它看起来像解决方案。
    • 但是这个库 github.com/artiomchi/FlexLabs.Upsert 只能更新一行。我认为我的问题的解决方案是从数据库中手动选择现有行(根据参数CustomerIdPushTemplateIdSent),从列表中排除这些行以进行插入,然后插入。但我不确定性能。
    【解决方案2】:

    也许您的模型在控制器中解析为 Action 可能没有准确的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多