EntityFramework-Reverse-POCO-Code-First-Generator icon indicating copy to clipboard operation
EntityFramework-Reverse-POCO-Code-First-Generator copied to clipboard

Can't add to views because they have no primary key

Open qrjo opened this issue 5 years ago • 5 comments

In v2 of the template all non-null columns of a view would automatically be set as primary keys. This no longer works, even though there is a comment in the settings that says it still should happen. See this line.

I know that views work in EF Core without primary keys, but I need to insert to views for my unit tests. So it'd be nice to get an opt-in for the old functionality.

qrjo avatar May 20 '20 16:05 qrjo

Hi @qrjo This functionality still exits in v3. See this function.

Set a breakpoint in that function at if (IsView && Settings.IsEfCore3()) and debug it to see what is going on. It could be that the view has all null columns.

sjh37 avatar May 20 '20 17:05 sjh37

Well, I'm using EF Core 3, so it returns there without setting a primary key. I still want primary keys though, because I cannot insert entities into my views otherwise.

qrjo avatar May 20 '20 18:05 qrjo

You can't insert any entities into views anyway. That's impossible as it's a view (only a select statement). If you want to insert data into the database, you use the core tables, not views.

sjh37 avatar May 21 '20 08:05 sjh37

Like I said, I need to insert entities into my views for unit tests.

qrjo avatar May 25 '20 09:05 qrjo

@qrjo Apologies. Should of read your question better. Create your fake db context, and add your test data to your views:

For example, CurrentProductLists is a view from the Northwind database.

[TestFixture]
public class ViewTesting
{
    private FakeMyDbContext _db;

    [SetUp]
    public void SetUp()
    {
        _db = new FakeMyDbContext();

        _db.CurrentProductLists.AddRange(
            new CurrentProductList
            {
                ProductId = 1,
                ProductName = "Hello"
            },
            new CurrentProductList
            {
                ProductId = 2,
                ProductName = "World"
            });
    }

    [Test]
    public void SimpleTest()
    {
        foreach (var list in _db.CurrentProductLists)
        {
            Console.WriteLine($"{list.ProductId} {list.ProductName}");
        }
    }
}

The output of the above test is

1 Hello
2 World

That view does not have a primary key defined in the FakeDbContext as it was created as:

CurrentProductLists = new FakeDbSet<CurrentProductList>();

Ones that do contain a primary key have the PKs passes as a parameter:

Orders = new FakeDbSet<Order>("OrderId");

Not having a primary key in the FakeDbSet means you can't call .Find

sjh37 avatar May 26 '20 09:05 sjh37