简体   繁体   中英

EF core ignore navigational property on save

It is just an illustratory example, I understand the relations in this example do not make sense perse, but it plots relations in a way I need the solution. So please do not comment about that.

I am searching for a solution in which I can ignore saving a navigational property;

public class ClassRoom {
    public Guid Id { get; set; }
    public Guid? ClassRoomInformationId { get; set; }
    
    public virtual ClassRoomInformation { get; set; }
    public virtual Collection<Student> Students { get; set; 
}

public class Student {
    public Guid Id { get; set; }
    public Guid? ClassRoomId { get; set; }
    public Guid? StudentInformationId { get; set; }

    public virtual StudentInformation { get; set; }
}

public class StudentEntityConfiguration : IEntityTypeConfiguration<Student> {
    public void Configure(EntityTypeBuilder<Student> builder) {
        builder.ToTable("Student");
        builder.HasKey(s => s.Id);

        builder.HasOne(s => s.StudentInformation)
            .WithOne()
            .HasForeignKey<Student>(s => s.StudentInformationId);
    }
}

public class ClassRoomEntityConfiguration : IEntityTypeConfiguration<ClassRoom> {
    public void Configure(EntityTypeBuilder<ClassRoom> builder) {
        builder.ToTable("ClassRoom");
        builder.HasKey(c => c.Id);

        builder.HasOne(c => c.ClassRoomInformation)
            .WithOne()
            .HasForeignKey<ClassRoom>(c => c.ClassRoomInformationId);

        builder.HasMany(c => c.Students)
            .WithOne()
            .HasForeignKey(c => c.ClassRoomInformation);
    }
}

To clearify my question (Using EF 2.2); I want to update the student through it's own StudentRepository. And when I save a classroom through the ClassRoomRepository and the student might change in any way, I do not want that change to be persisted (even though it is included to be able to 'view' the data).

I have tried to add the following to the ClassRoomEntityConfiguration:

//BeforeSaveBehavior neither works
builder.Property(c => c.Students).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;

However this gives the following exception: ... Cannot be used as a property on... because it is configured as a navigation.'

Another thing I tried is setting the componentmodel readonly attribute on the Students list in the ClassRoom. This seems to be ignored as well.

I call this the goldilocks problem. You have a hierarchy of objects (Customer, Order, OrderDetails) and you only want to save at "just the right level" of the object-graph.

A work around is to load the object......change only thing things that you care about, then save it.

In the below, I am NOT saving the inputItem.

I am using inputItem to set a small subset of the values of the foundEntity.

public async Task<MyThing> UpdateAsync(MyThing inputItem, CancellationToken token)
{
    int saveChangesAsyncValue = 0;
    MyThing foundEntity = await this.entityDbContext.MyThings.FirstOrDefaultAsync(item => item.MySurrogateKey == inputItem.MySurrogateKey, token);
    if (null != foundEntity)
    {

         /* alter JUST the things i want to update */
        foundEntity.MyStringPropertyOne = inputItem.MyStringPropertyOne;
        foundEntity.MyStringPropertyTwo = inputItem.MyStringPropertyTwo;


        this.entityDbContext.Entry(foundEntity).State = EntityState.Modified;

        saveChangesAsyncValue = await this.entityDbContext.SaveChangesAsync(token);

        /* an exception here would suggest another process changed the "context" but did not commit the changes (usually by SaveChanges() or SaveChangesAsync() */
        if (1 != saveChangesAsyncValue)
        {
            throw new ArgumentOutOfRangeException(string.Format("The expected count was off.  Did something else change the dbcontext and not save it?  {0}", saveChangesAsyncValue), (Exception)null);
        }
    }
    else
    {
        ArgumentOutOfRangeException argEx = new ArgumentOutOfRangeException(string.Format(" SAD FACE {0} ", entity.MyThingKey), (Exception)null);
        this.logger.LogError(argEx);
        throw argEx;
    }

    return foundEntity;
}

SIDE NOTE:

2.2 is no longer supported (see link below). Dot Net Core 2.2 End of Lifetime is listed as "December 23, 2019"

You should upgrade to 3.1 or downgrade to 2.1. (downgrading is counter intuitive I know).

See

https://dotnet.microsoft.com/platform/support/policy/dotnet-core

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM