Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having a keyless detail scaffolds wrong code #18633

Closed
MihaMarkic opened this issue Oct 29, 2019 · 12 comments
Closed

Having a keyless detail scaffolds wrong code #18633

MihaMarkic opened this issue Oct 29, 2019 · 12 comments
Assignees
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported good first issue This issue should be relatively straightforward to fix. Servicing-approved type-bug
Milestone

Comments

@MihaMarkic
Copy link

When having a keyless table in SQL server, scaffolding would generate entity navigation code between master and detail. The code fails at runtime when context is created.
I assume the code shouldn't throw an exception and probably scaffolding shouldn't generate it in first place.
Is this a scaffolding or EF Core issue?

'The navigation '' cannot be added because it targets the keyless entity type 'Detail'. Navigations can only target entity types with keys.'

Steps to reproduce

Create a master and detail tables in sql server with detail having no PK.
Scaffold the database and make an EF query.
The code will throw an exception in

modelBuilder.Entity<Detail>(entity =>
entity.HasNoKey();
...
entity.HasOne(d => d.Master)
                    .WithMany(p => p.Detail)
...

Exception:
'The navigation '' cannot be added because it targets the keyless entity type 'Detail'. Navigations can only target entity types with keys.'
-->

Further technical details

EF Core version: 3.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: ASP.NET Core 3.0
Operating system: Windows 10
IDE: (e.g. Visual Studio 2019 16.3.6)

@divinebovine
Copy link

divinebovine commented Oct 30, 2019

I am having the same issue with a scaffolded database, but I am unable to navigate any entity. It's as if the existence of an entity without a key is breaking navigation.

Example Model:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MyDb.Models
{
    public partial class AccessLog
    {
        [Key]
        [Column("UID")]
        public int Uid { get; set; }
        [Column(TypeName = "datetime")]
        public DateTime LogTime { get; set; }
        [Required]
        [StringLength(50)]
        public string Instance { get; set; }
        [Required]
        [StringLength(24)]
        public string Event { get; set; }
        [StringLength(128)]
        public string Username { get; set; }
        [StringLength(24)]
        public string Result { get; set; }
        public string Details { get; set; }
    }
}

Excerpt from Context.cs:

// omitting code
public virtual DbSet<AccessLog> AccessLog { get; set; }
// omitting code

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
	modelBuilder.Entity<AccessLog>(entity =>
	{
		entity.Property(e => e.Details).IsUnicode(false);

		entity.Property(e => e.Event).IsUnicode(false);

		entity.Property(e => e.Instance).IsUnicode(false);

		entity.Property(e => e.Result).IsUnicode(false);

		entity.Property(e => e.Username).IsUnicode(false);
	});
	
	// omitting code
}

Unit test with exception:

[Fact]
public async void Test_Insert_Access_Log()
{
	var options = new DbContextOptionsBuilder<SMPLContext>()
		.UseInMemoryDatabase(databaseName: nameof(Test_Insert_Access_Log))
		.Options;

	using var context = new Context(options);
	var accessLog = new AccessLog
	{
		LogTime =  DateTime.UtcNow,
		Instance =  "instance",
		Event =     "event",
		Username =  "user",
		Result =    "result",
		Details =   "details"
	};

	var logCount = await context.AccessLog.CountAsync().ConfigureAwait(false);
	Assert.Equal(0, logCount);

	context.AccessLog.Add(accessLog);
	await context.SaveChangesAsync().ConfigureAwait(false);

	logCount = await context.AccessLog.CountAsync().ConfigureAwait(false);
	Assert.Equal(1, logCount);
}

Exception:
image

@ajcvickers
Copy link
Member

Note for triage: talked to @AndriySvyryd and it looks like scaffolding should be generating a uni-direction navigation property here. For example:

entity.HasOne(d => d.Master).WithMany()

This is because keyless entity types cannot have incoming navigations, but can be at the dependent end of a unidirectional navigation to the principal.

@smitpatel
Copy link
Member

It could also be HaseOne().WithOne();

@ajcvickers ajcvickers added this to the Backlog milestone Nov 1, 2019
@ajcvickers
Copy link
Member

Note from triage: we should generate a unidirectional relationship here.

@Pzixel
Copy link

Pzixel commented Mar 24, 2020

@bricelam still facing this issue on 5.0.0-preview.2.20120.8. Can I do anything to mitigate it?


Fixed it by replacing HasNoKey() with my surrogate key .HasKey(t => new { t.CarId, t.PersonId });. Not sure if it how it should be, but it worked. At least I can perform readonly queries.

@DustSwiffer
Copy link

DustSwiffer commented Apr 30, 2020

Fixed it by replacing HasNoKey() with my surrogate key .HasKey(t => new { t.CarId, t.PersonId });. Not sure if it how it should be, but it worked. At least I can perform readonly queries.

Was the error occured after running the scaffold or was this a mistake made by yourself and did you fix it yourself afterwards?

@Pzixel
Copy link

Pzixel commented Apr 30, 2020

I didn't spot any errors during scaffolding, I did fix it manually afterwards when scaffolded DbContext failed to connect to the actual DB>

@MuhammadTalha10
Copy link

I am facing same issue is there any solution ?

@angelaki
Copy link

Is there a solution, yet? Still exists with EF6

@ajcvickers
Copy link
Member

@angelaki Please file a new issue and include the SQL for the tables that are being scaffolded and the code that is scaffolded so that we can investigate.

@angelaki
Copy link

@ajcvickers so it actually should work? Since my use-case, at least this time 😉, is quite straight forward I'd say. If so, I'll create one.

@ajcvickers
Copy link
Member

@angelaki This issue was fixed in version 3.1.3, as the milestone indicates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported good first issue This issue should be relatively straightforward to fix. Servicing-approved type-bug
Projects
None yet
Development

No branches or pull requests

9 participants