1

We have a .NET Framework 4.8 application that uses Entity Framework 6.

Now we are having a problem that we need to add some tables that don't guarantee any uniqueness (no primary key and rows can duplicate). There is no way to change the tables because it might break things (this table is re-populated 4AM everyday by a program that we can't control).

Pretty much the exact same problem as described in this question, but the answer simply said don't use Entity Framework 6. Another alternative I can think of is to have a view or have another program that imports the data of this table to a new table.

Is there really no Fluent API or Annotation workaround on the Entity Framework side? Do I really need to introduce a whole new way to access our database or introduce a new view just because in EF6 an entity must have a primary key?

Example of the tables' relation (actual table but I've removed most unrelated columns):

class Customer 
{
    [Key]
    public int CustomerID { get; set; }
    public string FirstName { get; set; }
    public virtual ICollection<CustomerOutboundEvent> CustomerOutboundEvents { get; set; }
}

// The new table
class CustomerOutboundEvent 
{
    // Adding key that doesn't actually exist will cause this error: Invalid column name 'CustomerOutboundEventID'.
    //[Key]
    //public int CustomerOutboundEventID { get; set; }
    public int CustomerID { get; set; }
    public Customer Customer { get; set; }
    public string OutboundNumber { get; set; }
    public string EventMessage { get; set; }
}
5
  • ED is an ORM, not a database driver. Why use it if you can't specify how to map objects to rows? Just to map the results? In that case it's better to use Dapper. don't use Entity Framework 6 yes, if you don't want an ORM, don't use an ORM. Commented Apr 8 at 13:54
  • What are the tables ? What you posted is the entity classes, not the tables. How do you determine which events are for each customer? Can you really have identical outbound event rows? Wont that result in eg duplicate emails sent to each customer? Commented Apr 8 at 13:58
  • @PanagiotisKanavos Not sure how EF6 is implemented but I imagine I don't need a foriegn key on the events table to determine which customer they belong to. It has a CustomerID column. As for why duplicates, a same event message can happen twice on a customer. (Imaging the same outbound customer error happened twice in a row.) Frankly we can't control anything about that table. Commented Apr 8 at 14:43
  • @PanagiotisKanavos As for the previous question, I know it is an ORM and I enjoy using it. We were using ADO.NET in DataSets with a bunch of messy table adpaters and EF6 is a HUGE improvement on the developer's side, and didn't bring much performance issue. I want an ORM, it's just that 1 out of 300 tables can't use it because of this specific reason, so I'm asking if there is a workaround. I'm not familer with Dapper but I would rather not migrate away from EF6 just because of this issue. (Unless mixing it is actually a good idea? I'm not sure.) Commented Apr 8 at 14:46
  • @PanagiotisKanavos Sorry typo, I mean I don't need a primary key on the events table to determine which customer they belong to because it has a customerID foriegn key. Commented Apr 8 at 15:27

1 Answer 1

3

You can lie about which columns are the key column in the table if you never use change tracking when querying the table.

To disable change tracking see: https://learn.microsoft.com/en-us/ef/ef6/querying/no-tracking

Since you have duplicates, even adding every column as a key column in EF won't make change tracking work, as EF refuses to load duplicates into the change tracker.

EF Core has Keyless Types

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks that works! Do you know if it is possible to disable it by default on the DBSet?
You can have a property of type IQueryable<EntityType> that returns an IQueryable pre-configured with .AsNoTracking(), and not have a DbSet for that entity at all. You just need to register the type as an entity in the fluent API.
I see, but the IQueryable<CustomerOutboundEvent> mytype=>Set<CustomerOutboundEvent>().AsNoTracking() property need to be under the DbContext class, so the navigation property in Customer won't be able to navigate to CustomerOutboundEvent with .AsNoTracking() by default right?
Right. But you can configure the IQueryable to return Customer with CustomerOutboundEvent included and AsNoTracking.
Makes sense to add a new IQuerable property that specifically for returning customer with event.AsNoTracking() instead of trying to hack the navigation property in Customer (which isn't allowed anyway.) Especially in my case many of those tables are even simpler that won't exist in any navigation. For those I'll even not add any DbContext but use IQueryable instead, thank you so much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.