Example #1
0
        private static async Task GetPersonsAsync_LazyLoading()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    // Run this with an SQL Server Profiler to see what's going on.
                    // Notice that this query has no explicit or eager loading of PersonContactNumber.
                    var persons = await unitOfWork.PersonRepository.GetAllAsync();

                    // The PersonContactNumbers navigation property in the Person object must also be
                    // marked as virtual for lazy loading to work.
                    foreach (var person in persons)
                    {
                        // When the PersonContactNumbers is being used, a separate query is then sent
                        // to the Database to obtain the particular records.
                        // This is the famous N+1 problem, 1 initial query to the database, but due to looping,
                        // N times other query is sent to the database!!
                        var personContactNumbers = person.PersonContactNumbers;

                        // Lazy loading should be avoided at all costs, unless the developer
                        // knows clearly what the f**k is going on.
                    }
                }
            }
        }
Example #2
0
        static void Main(string[] args)
        {
            IHost host = CreateHostBuilder(args).Build();
            Task  task = host.RunAsync();
            User  user = new User()
            {
                Name  = "111",
                Blogs = new System.Collections.Generic.List <Blog> {
                    new Blog {
                        Url = "htts://dev.haocai.com.cn", Posts = new System.Collections.Generic.List <Post> {
                            new Post {
                                Title = "1111"
                            }, new Post {
                                Title = "2222"
                            }
                        }
                    }
                }
            };
            EFDemoContext context = host.Services.GetService <EFDemoContext>();

            context.Database.EnsureDeleted();
            context.Database.Migrate();


            EntityEntry <User> ent = context.Set <User>().Add(user);

            context.SaveChanges();
            user.Name = "CCCC";
            context.SaveChanges();
            Console.ReadKey();
        }
Example #3
0
        private static async Task UpdateRecordsWithoutSelectAsync(IEnumerable <Person> persons)
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    var currentDateTime = DateTime.Now;
                    foreach (var person in persons)
                    {
                        person.DateOfBirth = currentDateTime;

                        // A single column update for Birthday.
                        unitOfWork.PersonRepository.UpdateBirthdayOnly(person);
                    }
                    await unitOfWork.CompleteAsync();

                    // Take a look at the Database at this point.

                    foreach (var person in persons)
                    {
                        person.FirstName = $"Updated {person.FirstName}";
                        person.LastName  = $"Updated {person.LastName}";

                        unitOfWork.PersonRepository.Update(person);
                    }
                    await unitOfWork.CompleteAsync();

                    // Take a look at the Database at this point.
                }
            }
        }
Example #4
0
        private static async Task <IEnumerable <Person> > UpdateRecordsWithSelectAsync()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    // Observe the gender property of each person here.
                    // The Gender navigation property is not explicitly joined in the query,
                    // so it will be NULL for all person objects.
                    var persons = await unitOfWork.PersonRepository.GetAllAsync();

                    // Observe the gender property of each person above AGAIN.
                    // The gender navigation property is automatically populated as EntityFramework
                    // has decided that the Gender navigation property is the same by comparing the
                    // GenderID of person to the ID of Gender under the same EFDemoContext scope.
                    var genders = await unitOfWork.GenderRepository.GetAllAsync();

                    // Since the objects are tracked and within the same scope,
                    // updating the values implies an Update query to the database.
                    // The downside of this kind of operation is that the data has to be first selected
                    // from the database before the values can be updated, what if we simply want to update
                    // a record without selecting it first?
                    foreach (var person in persons)
                    {
                        person.DateOfBirth = DateTime.Now.AddYears(10);
                    }

                    await unitOfWork.CompleteAsync();

                    return(persons);
                }
            }
        }
Example #5
0
        private static async Task GetPersonsAsync_EagerOrExplicitLoading()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    // This performs an inner join.
                    var personsWithContact = await unitOfWork.PersonRepository
                                             .GetPersonsWithContactNumbersAsync_EagerLoading();

                    // This is ORM exclusive, 2 separate queries are sent to the Database.
                    //var personsWithContact = await unitOfWork.PersonRepository
                    //    .GetPersonsWithContactNumbersAsync_ExplicitLoading();
                }
            }
        }
Example #6
0
        static void Main(string[] args)
        {
            var ninja = new Ninjas
            {
                Name             = "SampsonSan",
                ServedInOniwaban = false,
                ClanId           = 1
            };

            using (var context = new EFDemoContext())
            {
                // context.Database.Log = Console.WriteLine;
                context.Ninjas.Add(ninja);
                context.SaveChanges();
            }

            Console.WriteLine("Hello World!");
        }
Example #7
0
        private static async Task RemovePersonsAsync()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    // No difference for eager or explicit loading.
                    var personsWithContact = await unitOfWork.PersonRepository
                                             .GetPersonsWithContactNumbersAsync_ExplicitLoading();

                    unitOfWork.PersonRepository.RemoveRange(personsWithContact);

                    // Notice that PersonContactNumber is dependent on Person,
                    // a deletion on Person will cascade to PersonContactNumber as well.
                    await unitOfWork.CompleteAsync();
                }
            }
        }
Example #8
0
        static void Main(string[] args)
        {
            List <Student> students = null;

            using (var db = new EFDemoContext())
            {
                students = db.Student.Include("Course").ToList();
            }

            foreach (var item in students)
            {
                Console.WriteLine(item.Identity);
                Console.WriteLine(item.Name);
                Console.WriteLine(item.LastName);
                Console.WriteLine(item.Age);
                Console.WriteLine(item.CourseId);
                Console.WriteLine(item.Course.Name);
            }

            Console.ReadKey();
        }
Example #9
0
        private static async Task UpdateRecordsWithoutTrackingAsync()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    var untrackedPersons = await unitOfWork.PersonRepository.GetAllAsNoTrackingAsync();

                    foreach (var untrackedPerson in untrackedPersons)
                    {
                        // Everything done here will not make a difference.
                        untrackedPerson.FirstName = string.Empty;
                        untrackedPerson.LastName  = string.Empty;
                    }

                    // Untracked entities are detached from EntityFramework and
                    // the following line will have no effect.
                    await unitOfWork.CompleteAsync();
                }
            }
        }
Example #10
0
 public PersonRepository(EFDemoContext efDemoContext) : base(efDemoContext)
 {
     _efDemoContext = efDemoContext;
 }
Example #11
0
 public MainBaseService(EFDemoContext context)
 {
     _context = context;
 }
 public UnitOfWork(EFDemoContext efDemoContext)
 {
     _efDemoContext = efDemoContext;
 }
Example #13
0
 public OtherBaseService(EFDemoContext context)
 {
     _context = context;
 }
Example #14
0
        private static async Task InsertDummyDataAsync()
        {
            using (var efDemoContext = new EFDemoContext())
            {
                // The unit of work exposes the repositories and controls the transaction.
                // The repository provides persistence ignorance, as in the caller doesn't have
                // the knowledge where and how the data is being read or saved.
                // This obeys the principle of abstraction.
                // The responsibility to return data is on the repository and not the service!
                using (var unitOfWork = new UnitOfWork(efDemoContext))
                {
                    // This is the very first call of the efDemoContext.
                    // Since we have enabled Automatic migrations, 3 things will now happen.
                    // 1. EntityFramework will check if the database exists based on the definition in the connection string.
                    //    If not exist, EntityFramework will generate SQL scripts based on the POCO models defined by the EFDemoContext.
                    //    The SQL scripts will then be executed by the SQL intance defined by the connection string.
                    // 2. The Seed method in Configuration.cs will run once to seed the database.
                    // 3. The query, in this case, check if any person exists, will then be run.
                    var isDummyDataInserted = await unitOfWork.PersonRepository.AnyAsync();

                    if (isDummyDataInserted)
                    {
                        return;
                    }

                    var genders = await unitOfWork.GenderRepository.GetAllAsync();

                    var male   = genders.Single(g => g.Name == "Male");
                    var female = genders.Single(g => g.Name == "Female");

                    var aragorn = new Person
                    {
                        FirstName   = "Aragorn",
                        LastName    = "Elessar",
                        DateOfBirth = new DateTime(1991, 3, 14),
                        // Using the navigation property of gender.
                        Gender = male,
                        PersonContactNumbers = new List <PersonContactNumber>
                        {
                            // The relationship is implicit here, no need to define PersonID.
                            new PersonContactNumber {
                                PhoneNumber = "86930853"
                            }
                        }
                    };
                    var arwen = new Person
                    {
                        FirstName   = "Arwen",
                        LastName    = "Undomiel",
                        DateOfBirth = new DateTime(1996, 5, 10),
                        Gender      = female
                    };
                    var gandalf = new Person
                    {
                        FirstName   = "Gandalf",
                        LastName    = "Greyhame",
                        DateOfBirth = new DateTime(1900, 12, 12),
                        // Using the foreign key of gender, works the same as navigation property!
                        GenderID             = male.ID,
                        PersonContactNumbers = new List <PersonContactNumber>
                        {
                            new PersonContactNumber {
                                PhoneNumber = "88889999"
                            },
                            new PersonContactNumber {
                                PhoneNumber = "77776666"
                            }
                        }
                    };

                    // The following is normally called in the Service layer.
                    unitOfWork.PersonRepository.Add(aragorn);
                    unitOfWork.PersonRepository.AddRange(new List <Person> {
                        arwen, gandalf
                    });

                    // This is normally called in the Controller layer.
                    // The transaction is controlled such that any exception that happens in
                    // the service layer will bubble up and hence the following line will not be called!
                    await unitOfWork.CompleteAsync();
                }
            }
        }