using System; using System.Collections.Generic; using System.Data; using System.Linq; using Dapper.Contrib.Extensions; #if !COREFX using System.Data.SqlServerCe; using System.Transactions; #endif #if XUNIT2 using FactAttribute = Dapper.Tests.Contrib.SkippableFactAttribute; #else using Xunit; #endif namespace Dapper.Tests.Contrib { [Table("ObjectX")] public class ObjectX { [ExplicitKey] public string ObjectXId { get; set; } public string Name { get; set; } } [Table("ObjectY")] public class ObjectY { [ExplicitKey] public int ObjectYId { get; set; } public string Name { get; set; } } [Table("ObjectZ")] public class ObjectZ { [ExplicitKey] public int Id { get; set; } public string Name { get; set; } } public interface IUser { [Key] int Id { get; set; } string Name { get; set; } int Age { get; set; } } public class User : IUser { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } public class Person { public int Id { get; set; } public string Name { get; set; } } [Table("Stuff")] public class Stuff { [Key] public short TheId { get; set; } public string Name { get; set; } public DateTime? Created { get; set; } } [Table("Automobiles")] public class Car { public int Id { get; set; } public string Name { get; set; } [Computed] public string Computed { get; set; } } [Table("Results")] public class Result { public int Id { get; set; } public string Name { get; set; } public int Order { get; set; } } public abstract partial class TestSuite { protected static readonly bool IsAppVeyor = Environment.GetEnvironmentVariable("Appveyor")?.ToUpperInvariant() == "TRUE"; public abstract IDbConnection GetConnection(); private IDbConnection GetOpenConnection() { var connection = GetConnection(); connection.Open(); return connection; } [Fact] public void Issue418() { using (var connection = GetOpenConnection()) { //update first (will fail) then insert //added for bug #418 var updateObject = new ObjectX { ObjectXId = Guid.NewGuid().ToString(), Name = "Someone" }; var updates = connection.Update(updateObject); updates.IsFalse(); connection.DeleteAll(); var objectXId = Guid.NewGuid().ToString(); var insertObject = new ObjectX { ObjectXId = objectXId, Name = "Someone else" }; connection.Insert(insertObject); var list = connection.GetAll(); list.Count().IsEqualTo(1); } } /// /// Tests for issue #351 /// [Fact] public void InsertGetUpdateDeleteWithExplicitKey() { using (var connection = GetOpenConnection()) { var guid = Guid.NewGuid().ToString(); var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" }; var originalxCount = connection.Query("Select Count(*) From ObjectX").First(); connection.Insert(o1); var list1 = connection.Query("select * from ObjectX").ToList(); list1.Count.IsEqualTo(originalxCount + 1); o1 = connection.Get(guid); o1.ObjectXId.IsEqualTo(guid); o1.Name = "Bar"; connection.Update(o1); o1 = connection.Get(guid); o1.Name.IsEqualTo("Bar"); connection.Delete(o1); o1 = connection.Get(guid); o1.IsNull(); const int id = 42; var o2 = new ObjectY { ObjectYId = id, Name = "Foo" }; var originalyCount = connection.Query("Select Count(*) From ObjectY").First(); connection.Insert(o2); var list2 = connection.Query("select * from ObjectY").ToList(); list2.Count.IsEqualTo(originalyCount + 1); o2 = connection.Get(id); o2.ObjectYId.IsEqualTo(id); o2.Name = "Bar"; connection.Update(o2); o2 = connection.Get(id); o2.Name.IsEqualTo("Bar"); connection.Delete(o2); o2 = connection.Get(id); o2.IsNull(); } } [Fact] public void GetAllWithExplicitKey() { using (var connection = GetOpenConnection()) { var guid = Guid.NewGuid().ToString(); var o1 = new ObjectX { ObjectXId = guid, Name = "Foo" }; connection.Insert(o1); var objectXs = connection.GetAll().ToList(); objectXs.Count.IsMoreThan(0); objectXs.Count(x => x.ObjectXId== guid).IsEqualTo(1); } } [Fact] public void InsertGetUpdateDeleteWithExplicitKeyNamedId() { using (var connection = GetOpenConnection()) { const int id = 42; var o2 = new ObjectZ { Id = id, Name = "Foo" }; connection.Insert(o2); var list2 = connection.Query("select * from ObjectZ").ToList(); list2.Count.IsEqualTo(1); o2 = connection.Get(id); o2.Id.IsEqualTo(id); //o2.Name = "Bar"; //connection.Update(o2); //o2 = connection.Get(id); //o2.Name.IsEqualTo("Bar"); //connection.Delete(o2); //o2 = connection.Get(id); //o2.IsNull(); } } [Fact] public void ShortIdentity() { using (var connection = GetOpenConnection()) { const string name = "First item"; var id = connection.Insert(new Stuff { Name = name }); id.IsMoreThan(0); // 1-n are valid here, due to parallel tests var item = connection.Get(id); item.TheId.IsEqualTo((short)id); item.Name.IsEqualTo(name); } } [Fact] public void NullDateTime() { using (var connection = GetOpenConnection()) { connection.Insert(new Stuff { Name = "First item" }); connection.Insert(new Stuff { Name = "Second item", Created = DateTime.Now }); var stuff = connection.Query("select * from Stuff").ToList(); stuff.First().Created.IsNull(); stuff.Last().Created.IsNotNull(); } } [Fact] public void TableName() { using (var connection = GetOpenConnection()) { // tests against "Automobiles" table (Table attribute) var id = connection.Insert(new Car { Name = "Volvo" }); var car = connection.Get(id); car.IsNotNull(); car.Name.IsEqualTo("Volvo"); connection.Get(id).Name.IsEqualTo("Volvo"); connection.Update(new Car { Id = (int)id, Name = "Saab" }).IsEqualTo(true); connection.Get(id).Name.IsEqualTo("Saab"); connection.Delete(new Car { Id = (int)id }).IsEqualTo(true); connection.Get(id).IsNull(); } } [Fact] public void TestSimpleGet() { using (var connection = GetOpenConnection()) { var id = connection.Insert(new User { Name = "Adama", Age = 10 }); var user = connection.Get(id); user.Id.IsEqualTo((int)id); user.Name.IsEqualTo("Adama"); connection.Delete(user); } } [Fact] public void TestClosedConnection() { using (var connection = GetConnection()) { connection.Insert(new User { Name = "Adama", Age = 10 }).IsMoreThan(0); var users = connection.GetAll(); users.Count().IsMoreThan(0); } } [Fact] public void InsertArray() { InsertHelper(src => src.ToArray()); } [Fact] public void InsertList() { InsertHelper(src => src.ToList()); } private void InsertHelper(Func, T> helper) where T : class { const int numberOfEntities = 10; var users = new List(); for (var i = 0; i < numberOfEntities; i++) users.Add(new User { Name = "User " + i, Age = i }); using (var connection = GetOpenConnection()) { connection.DeleteAll(); var total = connection.Insert(helper(users)); total.IsEqualTo(numberOfEntities); users = connection.Query("select * from Users").ToList(); users.Count.IsEqualTo(numberOfEntities); } } [Fact] public void UpdateArray() { UpdateHelper(src => src.ToArray()); } [Fact] public void UpdateList() { UpdateHelper(src => src.ToList()); } private void UpdateHelper(Func, T> helper) where T : class { const int numberOfEntities = 10; var users = new List(); for (var i = 0; i < numberOfEntities; i++) users.Add(new User { Name = "User " + i, Age = i }); using (var connection = GetOpenConnection()) { connection.DeleteAll(); var total = connection.Insert(helper(users)); total.IsEqualTo(numberOfEntities); users = connection.Query("select * from Users").ToList(); users.Count.IsEqualTo(numberOfEntities); foreach (var user in users) { user.Name = user.Name + " updated"; } connection.Update(helper(users)); var name = connection.Query("select * from Users").First().Name; name.Contains("updated").IsTrue(); } } [Fact] public void DeleteArray() { DeleteHelper(src => src.ToArray()); } [Fact] public void DeleteList() { DeleteHelper(src => src.ToList()); } private void DeleteHelper(Func, T> helper) where T : class { const int numberOfEntities = 10; var users = new List(); for (var i = 0; i < numberOfEntities; i++) users.Add(new User { Name = "User " + i, Age = i }); using (var connection = GetOpenConnection()) { connection.DeleteAll(); var total = connection.Insert(helper(users)); total.IsEqualTo(numberOfEntities); users = connection.Query("select * from Users").ToList(); users.Count.IsEqualTo(numberOfEntities); var usersToDelete = users.Take(10).ToList(); connection.Delete(helper(usersToDelete)); users = connection.Query("select * from Users").ToList(); users.Count.IsEqualTo(numberOfEntities - 10); } } [Fact] public void InsertGetUpdate() { using (var connection = GetOpenConnection()) { connection.DeleteAll(); connection.Get(3).IsNull(); //insert with computed attribute that should be ignored connection.Insert(new Car { Name = "Volvo", Computed = "this property should be ignored" }); var id = connection.Insert(new User { Name = "Adam", Age = 10 }); //get a user with "isdirty" tracking var user = connection.Get(id); user.Name.IsEqualTo("Adam"); connection.Update(user).IsEqualTo(false); //returns false if not updated, based on tracking user.Name = "Bob"; connection.Update(user).IsEqualTo(true); //returns true if updated, based on tracking user = connection.Get(id); user.Name.IsEqualTo("Bob"); //get a user with no tracking var notrackedUser = connection.Get(id); notrackedUser.Name.IsEqualTo("Bob"); connection.Update(notrackedUser).IsEqualTo(true); //returns true, even though user was not changed notrackedUser.Name = "Cecil"; connection.Update(notrackedUser).IsEqualTo(true); connection.Get(id).Name.IsEqualTo("Cecil"); connection.Query("select * from Users").Count().IsEqualTo(1); connection.Delete(user).IsEqualTo(true); connection.Query("select * from Users").Count().IsEqualTo(0); connection.Update(notrackedUser).IsEqualTo(false); //returns false, user not found } } #if !COREFX [Fact(Skip = "Not parallel friendly - thinking about how to test this")] public void InsertWithCustomDbType() { SqlMapperExtensions.GetDatabaseType = conn => "SQLiteConnection"; bool sqliteCodeCalled = false; using (var connection = GetOpenConnection()) { connection.DeleteAll(); connection.Get(3).IsNull(); try { connection.Insert(new User { Name = "Adam", Age = 10 }); } catch (SqlCeException ex) { sqliteCodeCalled = ex.Message.IndexOf("There was an error parsing the query", StringComparison.OrdinalIgnoreCase) >= 0; } // ReSharper disable once EmptyGeneralCatchClause catch (Exception) { } } SqlMapperExtensions.GetDatabaseType = null; if (!sqliteCodeCalled) { throw new Exception("Was expecting sqlite code to be called"); } } #endif [Fact] public void InsertWithCustomTableNameMapper() { SqlMapperExtensions.TableNameMapper = type => { switch (type.Name()) { case "Person": return "People"; default: var tableattr = type.GetCustomAttributes(false).SingleOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic; if (tableattr != null) return tableattr.Name; var name = type.Name + "s"; if (type.IsInterface() && name.StartsWith("I")) name = name.Substring(1); return name; } }; using (var connection = GetOpenConnection()) { var id = connection.Insert(new Person { Name = "Mr Mapper" }); id.IsEqualTo(1); connection.GetAll(); } } [Fact] public void GetAll() { const int numberOfEntities = 10; var users = new List(); for (var i = 0; i < numberOfEntities; i++) users.Add(new User { Name = "User " + i, Age = i }); using (var connection = GetOpenConnection()) { connection.DeleteAll(); var total = connection.Insert(users); total.IsEqualTo(numberOfEntities); users = connection.GetAll().ToList(); users.Count.IsEqualTo(numberOfEntities); var iusers = connection.GetAll().ToList(); iusers.Count.IsEqualTo(numberOfEntities); for (var i = 0; i < numberOfEntities; i++) iusers[i].Age.IsEqualTo(i); } } [Fact] public void Transactions() { using (var connection = GetOpenConnection()) { var id = connection.Insert(new Car { Name = "one car" }); //insert outside transaction var tran = connection.BeginTransaction(); var car = connection.Get(id, tran); var orgName = car.Name; car.Name = "Another car"; connection.Update(car, tran); tran.Rollback(); car = connection.Get(id); //updates should have been rolled back car.Name.IsEqualTo(orgName); } } #if !COREFX [Fact] public void TransactionScope() { using (var txscope = new TransactionScope()) { using (var connection = GetOpenConnection()) { var id = connection.Insert(new Car { Name = "one car" }); //inser car within transaction txscope.Dispose(); //rollback connection.Get(id).IsNull(); //returns null - car with that id should not exist } } } #endif [Fact] public void InsertCheckKey() { using (var connection = GetOpenConnection()) { connection.Get(3).IsNull(); User user = new User { Name = "Adamb", Age = 10 }; int id = (int)connection.Insert(user); user.Id.IsEqualTo(id); } } [Fact] public void BuilderSelectClause() { using (var connection = GetOpenConnection()) { var rand = new Random(8675309); var data = new List(); for (int i = 0; i < 100; i++) { var nU = new User { Age = rand.Next(70), Id = i, Name = Guid.NewGuid().ToString() }; data.Add(nU); nU.Id = (int)connection.Insert(nU); } var builder = new SqlBuilder(); var justId = builder.AddTemplate("SELECT /**select**/ FROM Users"); var all = builder.AddTemplate("SELECT Name, /**select**/, Age FROM Users"); builder.Select("Id"); var ids = connection.Query(justId.RawSql, justId.Parameters); var users = connection.Query(all.RawSql, all.Parameters); foreach (var u in data) { if (!ids.Any(i => u.Id == i)) throw new Exception("Missing ids in select"); if (!users.Any(a => a.Id == u.Id && a.Name == u.Name && a.Age == u.Age)) throw new Exception("Missing users in select"); } } } [Fact] public void BuilderTemplateWithoutComposition() { var builder = new SqlBuilder(); var template = builder.AddTemplate("SELECT COUNT(*) FROM Users WHERE Age = @age", new { age = 5 }); if (template.RawSql == null) throw new Exception("RawSql null"); if (template.Parameters == null) throw new Exception("Parameters null"); using (var connection = GetOpenConnection()) { connection.DeleteAll(); connection.Insert(new User { Age = 5, Name = "Testy McTestington" }); if (connection.Query(template.RawSql, template.Parameters).Single() != 1) throw new Exception("Query failed"); } } [Fact] public void InsertFieldWithReservedName() { using (var connection = GetOpenConnection()) { connection.DeleteAll(); var id = connection.Insert(new Result() { Name = "Adam", Order = 1 }); var result = connection.Get(id); result.Order.IsEqualTo(1); } } [Fact] public void DeleteAll() { using (var connection = GetOpenConnection()) { var id1 = connection.Insert(new User { Name = "Alice", Age = 32 }); var id2 = connection.Insert(new User { Name = "Bob", Age = 33 }); connection.DeleteAll().IsTrue(); connection.Get(id1).IsNull(); connection.Get(id2).IsNull(); } } } }