Pomelo.entityframeworkcore.mysql: How to create CHECK constraint Use Fluent API?

Created on 23 Sep 2019  Â·  1Comment  Â·  Source: PomeloFoundation/Pomelo.EntityFrameworkCore.MySql

I want to create a check constraint,eg gender

CREATE TABLE `test1` (
  `id` int(11)  NOT NULL AUTO_INCREMENT ,
  `gender` varchar(6) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  CONSTRAINT `constraint_gender` CHECK (`gender` = 'male' or `gender` = 'female')
)

I don't want use migrationBuilder.Sql() create check constraints, so I want to known Weather support Create a CHECK constraint Using Fluent API ? same as HasCheckConstraint...(I doesn't found).

Thank you for your help

closed-external closed-fixed type-question

Most helpful comment

HasCheckConstraint() was added in https://github.com/aspnet/EntityFrameworkCore/pull/14673 and then fixed in https://github.com/aspnet/EntityFrameworkCore/issues/17052 for EF Core 3.0.

I successfully checked our support for this in the 3.0.0-wip branch with the following test:

```c#
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.TestUtilities;
using MySql.Data.MySqlClient;
using Pomelo.EntityFrameworkCore.MySql.FunctionalTests.TestUtilities;
using Xunit;

namespace Pomelo.EntityFrameworkCore.MySql.FunctionalTests
{
public class ReportedIssuesMySqlTest
: IClassFixture
{
[ConditionalFact]
public virtual void TestIssue831()
{
using var context = CreateContext();

        context.Set<test1>()
            .Add(new test1 { gender = "trans" });

        var outerExpection = Assert.Throws<DbUpdateException>(() => context.SaveChanges());
        var innerException = Assert.IsType<MySqlException>(outerExpection.InnerException);
        Assert.Equal(
            innerException.Message,
            "Check constraint 'constraint_gender' is violated.");
    }

    public class test1
    {
        public int id { get; set; }
        public string gender { get; set; }
    }

    public class ReportedIssuesMySqlFixture : SharedStoreFixtureBase<PoolableDbContext>
    {
        protected override void OnModelCreating(
            ModelBuilder modelBuilder,
            DbContext context)
        {
            modelBuilder.Entity<test1>(entity =>
            {
                entity.HasKey(e => e.id);

                entity.Property(e => e.gender)
                    .HasMaxLength(6);

                entity.HasCheckConstraint(
                    "constraint_gender",
                    "`gender` = 'male' or `gender` = 'female'");
            });
        }

        protected override void Seed(PoolableDbContext context)
        {
            context.Set<test1>().AddRange(
                new test1 { gender = "male" },
                new test1 { gender = "female" }
            );

            context.SaveChanges();
        }

        protected override ITestStoreFactory TestStoreFactory
            => MySqlTestStoreFactory.Instance;

        protected override string StoreName { get; } = "ReportedIssues";
    }

    public ReportedIssuesMySqlTest(ReportedIssuesMySqlFixture fixture)
        => Fixture = fixture;

    protected ReportedIssuesMySqlFixture Fixture { get; }
    protected DbContext CreateContext() => Fixture.CreateContext();
}

}


This test throws the following exception (wrapped in a `DbUpdateException`) as expected:

MySql.Data.MySqlClient.MySqlException: 'Check constraint 'constraint_gender' is violated.'


The test generates the following SQL:

```sql
CREATE TABLE `test1` (
    `id` int NOT NULL AUTO_INCREMENT,
    `gender` varchar(6) NULL,
    CONSTRAINT `PK_test1` PRIMARY KEY (`id`),
    CONSTRAINT `constraint_gender` CHECK (`gender` = 'male' or `gender` = 'female')
);

@p0='male' (Size = 6)

INSERT INTO `test1` (`gender`)
VALUES (@p0);
SELECT `id`
FROM `test1`
WHERE ROW_COUNT() = 1 AND `id` = LAST_INSERT_ID();

@p0='female' (Size = 6)

INSERT INTO `test1` (`gender`)
VALUES (@p0);
SELECT `id`
FROM `test1`
WHERE ROW_COUNT() = 1 AND `id` = LAST_INSERT_ID();

>All comments

HasCheckConstraint() was added in https://github.com/aspnet/EntityFrameworkCore/pull/14673 and then fixed in https://github.com/aspnet/EntityFrameworkCore/issues/17052 for EF Core 3.0.

I successfully checked our support for this in the 3.0.0-wip branch with the following test:

```c#
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.TestUtilities;
using MySql.Data.MySqlClient;
using Pomelo.EntityFrameworkCore.MySql.FunctionalTests.TestUtilities;
using Xunit;

namespace Pomelo.EntityFrameworkCore.MySql.FunctionalTests
{
public class ReportedIssuesMySqlTest
: IClassFixture
{
[ConditionalFact]
public virtual void TestIssue831()
{
using var context = CreateContext();

        context.Set<test1>()
            .Add(new test1 { gender = "trans" });

        var outerExpection = Assert.Throws<DbUpdateException>(() => context.SaveChanges());
        var innerException = Assert.IsType<MySqlException>(outerExpection.InnerException);
        Assert.Equal(
            innerException.Message,
            "Check constraint 'constraint_gender' is violated.");
    }

    public class test1
    {
        public int id { get; set; }
        public string gender { get; set; }
    }

    public class ReportedIssuesMySqlFixture : SharedStoreFixtureBase<PoolableDbContext>
    {
        protected override void OnModelCreating(
            ModelBuilder modelBuilder,
            DbContext context)
        {
            modelBuilder.Entity<test1>(entity =>
            {
                entity.HasKey(e => e.id);

                entity.Property(e => e.gender)
                    .HasMaxLength(6);

                entity.HasCheckConstraint(
                    "constraint_gender",
                    "`gender` = 'male' or `gender` = 'female'");
            });
        }

        protected override void Seed(PoolableDbContext context)
        {
            context.Set<test1>().AddRange(
                new test1 { gender = "male" },
                new test1 { gender = "female" }
            );

            context.SaveChanges();
        }

        protected override ITestStoreFactory TestStoreFactory
            => MySqlTestStoreFactory.Instance;

        protected override string StoreName { get; } = "ReportedIssues";
    }

    public ReportedIssuesMySqlTest(ReportedIssuesMySqlFixture fixture)
        => Fixture = fixture;

    protected ReportedIssuesMySqlFixture Fixture { get; }
    protected DbContext CreateContext() => Fixture.CreateContext();
}

}


This test throws the following exception (wrapped in a `DbUpdateException`) as expected:

MySql.Data.MySqlClient.MySqlException: 'Check constraint 'constraint_gender' is violated.'


The test generates the following SQL:

```sql
CREATE TABLE `test1` (
    `id` int NOT NULL AUTO_INCREMENT,
    `gender` varchar(6) NULL,
    CONSTRAINT `PK_test1` PRIMARY KEY (`id`),
    CONSTRAINT `constraint_gender` CHECK (`gender` = 'male' or `gender` = 'female')
);

@p0='male' (Size = 6)

INSERT INTO `test1` (`gender`)
VALUES (@p0);
SELECT `id`
FROM `test1`
WHERE ROW_COUNT() = 1 AND `id` = LAST_INSERT_ID();

@p0='female' (Size = 6)

INSERT INTO `test1` (`gender`)
VALUES (@p0);
SELECT `id`
FROM `test1`
WHERE ROW_COUNT() = 1 AND `id` = LAST_INSERT_ID();
Was this page helpful?
0 / 5 - 0 ratings