1
votes

Suppose I have 2 tables with many to one relationship: Book -> Author. Author can have multiple books. So, Book entity has Author and AuthorId navigation properties.

For example Author table contains one row: AuthorName. I want to insert new Author only if the name is unique.

So, what I do:

var book = new Book();
var authorFromDatabase = getAuthorFromDbByName("author name");
if(authorFromDatabase == null)
{
    // insert new author if it is not already in the database
    book.Author = new Author("author name");
}
else
{
    // how to assign AuthorId to book so that it will not add new Author to the db??
    // the following line inserts new author into the db
    book.AuthorId = authorFromDatabase .AuthorId;
}

So, how can I assign AuthorId to book and not insert a new Author into the db if it's already there?

2
Is it code-first? Are the IDs generated by the DB?Alexander Schmidt
What about book.Author = authorFromDatabase;?Adriano Repetti
@sprinter252, it's database first, AuthorId is generated in the database.Aleksei Chepovoi
I would go with this: book.Author = authorFromDatabase ?? new Author("author name");Alexandre Machado
So is your problem uniqueness of the name?Alexander Schmidt

2 Answers

2
votes

Setting the .AuthorId property would not create a new Author in the DB - how could it? You're not actually constructing a new Author object and adding it to your DbContext. From what you've given us to look at, it would seem if(authorFromDatabase == null) always resolves as True. Have you debugged the code to ensure that the else block is ever executed?

You should probably show more of of your code, such as your Author and Book entity classes as well as your getAuthorFromDbByName(...) method implementation and where you instantiate your DbContext instances.

0
votes

If it is about uniqueness I would do something like this:

// some code
newBook.Author = CreateOrGetAuthor("The Name");
// more code

private Author CreateOrGetAuthor(string authorName)
{
    var author = _context.Authors.SingleOrDefault(a => a.Name.Equals(authorName, StringComparison.CurrentCultureIgnoreCase));
    if (author == null)
    {
        author = new Author();
        author.Name = authorName;
    }
    return author; 
}

Now it depends on if you're using transactions around those both calls. If not, you have to call _context.SaveChanges() first and the return the author in CreateOrGetAuthor. Otherwise it won't have an ID.