DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • From Naked Objects to Naked Functions
  • Working With Transactions in Entity Framework Core and Entity Developer
  • Working With Lazy Loading and Eager Loading in Entity Framework Core and Entity Developer
  • Why Text2SQL Alone Isn’t Enough: Embracing TAG

Trending

  • Beyond Conversation: Mastering Context with Claude Code Skills and Agents
  • Agentic AI Design Patterns and Principles: Building Autonomous, Collaborative Systems
  • Comparing Top Gen AI Frameworks for Java in 2026
  • Bringing Intelligence Closer to the Source: Why Real-Time Processing is the Heart of Edge AI
  1. DZone
  2. Coding
  3. Frameworks
  4. Entity Framework: new() vs. DbSet.Create()

Entity Framework: new() vs. DbSet.Create()

In Entity, the new and DbSet.Create methods have similar goals with different behaviors. See when to use which one when instantiating new entities.

By 
Tomasz Pęczek user avatar
Tomasz Pęczek
·
Jun. 08, 17 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
11.2K Views

Join the DZone community and get the full member experience.

Join For Free

This is one of those "I had to explain this couple times already so next time, I want something I can redirect people to" kind of post.

What I want to write about is the difference in behavior between using new() and DbSet.Create() for instantiating new entities. In order to do this, I've created a very simple model and context:

public class Planet {
    public virtual int Id {
        get;
        set;
    }
    public virtual string Name {
        get;
        set;
    }
    ...
    public virtual ICollection Natives {
        get;
        set;
    }
}

public class Character {
    public virtual int Id {
        get;
        set;
    }
    public virtual string Name {
        get;
        set;
    }
    ...
    public virtual int HomeworldId {
        get;
        set;
    }
    public virtual Planet Homeworld {
        get;
        set;
    }
}

public interface IStarWarsContext {
    DbSet Planets {
        get;
        set;
    }
    DbSet Characters {
        get;
        set;
    }
    int SaveChanges();
}

public class StarWarsContext: DbContext, IStarWarsContext {
    public DbSet Planets {
        get;
        set;
    }
    public DbSet Characters {
        get;
        set;
    }
}


I've also created a very simple view that lists characters already present in the database and allows for adding new ones.

@using (Html.BeginForm())
{
    <fieldset>
        <legend>New StarWars Character</legend>
        <div>
            @Html.LabelFor(m => m.Name)
        </div>
        <div>
            @Html.TextBoxFor(m => m.Name)
        </div>
        <div>
            @Html.LabelFor(m => m.Homeworld)
        </div>
        <div>
            @Html.DropDownListFor(m => m.Homeworld, Model.Planets)
        </div>
        ...
        <div>
            <input type="submit" value="Add" />
        </div>
    </fieldset>
}
<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Homeworld</th>
            ...
        </tr>
    </thead>
    <tbody>
        @foreach (Character character in Model.Characters)
        {
            <tr>
                <td>@character.Name</td>
                <td>@character.Homeworld.Name</td>
                ...
            </tr>
        }
    </tbody>
</table>


The view is powered by the following ViewModel and controller.

public class StarWarsViewModel {
    public string Name {
        get;
        set;
    }

    ...

    public int Homeworld {
        get;
        set;
    }

    public IEnumerable Planets {
        get;
        set;
    }

    public IReadOnlyList Characters {
        get;
        set;
    }
}

public class StarWarsController: Controller {
    private IStarWarsContext _startWarsContext;

    public StarWarsController(IStarWarsContext startWarsContext) {
        _startWarsContext = startWarsContext;
    }

    [HttpGet]
    public ActionResult Index() {
        return View(GetViewModel());
    }

    [HttpPost]
    public ActionResult Index(StarWarsViewModel viewModel) {
        AddCharacter(viewModel);

        return View(GetViewModel());
    }

    private StarWarsViewModel GetViewModel() {
        return new StarWarsViewModel {
            Planets = _startWarsContext.Planets
                .Select(p => new {
                    p.Id, p.Name
                })
                .ToList()
                .Select(p => new SelectListItem {
                    Value = p.Id.ToString(), Text = p.Name
                }),
                Characters = _startWarsContext.Characters.ToList()
        };
    }

    private void AddCharacter(StarWarsViewModel viewModel) {
        throw new NotImplementedException();
    }
}


The AddCharacter method is the point of interest here. There are two ways to implement it, and they will result in a different behavior.

Creating Entities With new()

Following the first Entity Framework tutorial that pops up on Google will result in code similar to this:

private void AddCharacter(StarWarsViewModel viewModel) {
    Character character = new Character();
    character.Name = viewModel.Name;
    ...
    character.HomeworldId = viewModel.Homeworld;

    _startWarsContext.Characters.Add(character);
    _startWarsContext.SaveChanges();
}


Running this code and adding a new Character will result in a NullReferenceException coming from the part of view that generates the table (to be more exact, it comes from @character.Homeworld.Name). The reason for the exception is the fact that Entity Framework needs to lazy load the Planet entity, but the just-added Character entity is not a dynamic proxy, so lazy loading doesn't work for it. Only Entity Framework can create a dynamic proxy, but in this scenario, there is no way for it to do that — the caller already owns the reference to the entity, and it cannot be changed to a different class.

Creating Entity With DbSet.Create()

In order to be able to create new entities as proper dynamic proxies, the DbSet class provides the Create method. This method returns a new dynamic proxy instance that isn't added or attached to the context. To use it, only a single line of code needs to be changed.

private void AddCharacter(StarWarsViewModel viewModel) {
    Character character = _startWarsContext.Characters.Create();
    character.Name = viewModel.Name;
    ...
    character.HomeworldId = viewModel.Homeworld;

    _startWarsContext.Characters.Add(character);
    _startWarsContext.SaveChanges();
}


After this simple change, the code works as expected — related entities are being lazy loaded when needed.

The Takeaway

The sample above is built in a way that highlights the difference between new() and DbSet.Create() (it even has an N+1 selects hiding in there for the sake of simplicity). In real life, this rarely causes an issue, as there are a couple of other things that can impact the behavior (related entity already present in context or usage of the Include() method, for example). But when this causes an issue, it's always unexpected, and I've seen smart people struggling to wrap their heads around what is going on. It is important to understand the difference and use both mechanisms appropriately (sometimes lack of lazy loading may be desired).

Database Entity Framework Framework

Published at DZone with permission of Tomasz Pęczek. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • From Naked Objects to Naked Functions
  • Working With Transactions in Entity Framework Core and Entity Developer
  • Working With Lazy Loading and Eager Loading in Entity Framework Core and Entity Developer
  • Why Text2SQL Alone Isn’t Enough: Embracing TAG

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook