GithubHelp home page GithubHelp logo

dapperlib / dapper.contrib Goto Github PK

View Code? Open in Web Editor NEW
241.0 11.0 91.0 46.87 MB

Dapper community contributions - additional extensions for Dapper

License: Other

Batchfile 0.16% PowerShell 1.05% C# 98.79%

dapper.contrib's Introduction

Dapper.Contrib - a simple object mapper for .Net

Build status

Release Notes

Located at dapperlib.github.io/Dapper.Contrib

Packages

MyGet Pre-release feed: https://www.myget.org/gallery/dapper

Package NuGet Stable NuGet Pre-release Downloads MyGet
Dapper.Contrib Dapper.Contrib Dapper.Contrib Dapper.Contrib Dapper.Contrib MyGet

Features

Dapper.Contrib contains a number of helper methods for inserting, getting, updating and deleting records.

The full list of extension methods in Dapper.Contrib right now are:

T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

For these extensions to work, the entity in question MUST have a key property. Dapper will automatically use a property named "id" (case-insensitive) as the key property, if one is present.

public class Car
{
    public int Id { get; set; } // Works by convention
    public string Name { get; set; }
}

If the entity doesn't follow this convention, decorate a specific property with a [Key] or [ExplicitKey] attribute.

public class User
{
    [Key]
    int TheId { get; set; }
    string Name { get; set; }
    int Age { get; set; }
}

[Key] should be used for database-generated keys (e.g. autoincrement columns), while [ExplicitKey] should be used for explicit keys generated in code.

Get methods

Get one specific entity based on id

var car = connection.Get<Car>(1);

or a list of all entities in the table.

var cars = connection.GetAll<Car>();

Insert methods

Insert one entity

connection.Insert(new Car { Name = "Volvo" });

or a list of entities.

connection.Insert(cars);

Update methods

Update one specific entity

connection.Update(new Car() { Id = 1, Name = "Saab" });

or update a list of entities.

connection.Update(cars);

Delete methods

Delete an entity by the specified [Key] property

connection.Delete(new Car() { Id = 1 });

a list of entities

connection.Delete(cars);

or ALL entities in the table.

connection.DeleteAll<Car>();

Special Attributes

Dapper.Contrib makes use of some optional attributes:

  • [Table("Tablename")] - use another table name instead of the (by default pluralized) name of the class

    [Table ("emps")]
    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
  • [Key] - this property represents a database-generated identity/key

    public class Employee
    {
        [Key]
        public int EmployeeId { get; set; }
        public string Name { get; set; }
    }
  • [ExplicitKey] - this property represents an explicit identity/key which is not automatically generated by the database

    public class Employee
    {
        [ExplicitKey]
        public Guid EmployeeId { get; set; }
        public string Name { get; set; }
    }
  • [Write(true/false)] - this property is (not) writeable

  • [Computed] - this property is computed and should not be part of updates

Limitations and caveats

SQLite

SQLiteConnection exposes an Update event that clashes with the Update extension provided by Dapper.Contrib. There are 2 ways to deal with this.

  1. Call the Update method explicitly from SqlMapperExtensions

    SqlMapperExtensions.Update(_conn, new Employee { Id = 1, Name = "Mercedes" });
  2. Make the method signature unique by passing a type parameter to Update

    connection.Update<Car>(new Car() { Id = 1, Name = "Maruti" });

dapper.contrib's People

Contributors

alexwiese avatar azhmur avatar bdrupieski avatar blackjacketmack avatar brannon avatar damirainullin avatar greygeek avatar henkmollema avatar jamesholwell avatar jedidja avatar jnm2 avatar joaomatossilva avatar jocapc avatar johandanforth avatar joncloud avatar mgravell avatar mrange avatar nickcraver avatar nigrimmist avatar obalix avatar panesofglass avatar samsaffron avatar sebastienros avatar seburgi avatar sergiivolchkov avatar shrayasr avatar sqmgh avatar tms avatar vosen avatar xps avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dapper.contrib's Issues

Insert returns 0 when using a string as an ExplicitKey on an object

Topic, this may also be related to DapperLib/Dapper#756 but i'm not sure if it's the same issue.
Here is the object I am using:

using Dapper.Contrib.Extensions;

[Table("CostBooks.Staff")]
public class Staff
{
    [ExplicitKey]
    public string EmplNbr { get; set; }
    public string AlphaName { get; set; }
    public bool? IsFte { get; set; }
}

Here is the method I am calling. Will try to do this with async and see what happens.

[HttpPost]
public object CreateNewStaff([FromBody]Staff s)
{
    using (IDbConnection db = DBAccessor.Connection())
    {
        if (s.EmplNbr != null)
        {
            var emplNbr = db.Insert<Staff>(s);
            return emplNbr
        }
        else
        {
            return null;
        }
    }
}

Dapper.Contrib Key caching issue

There is a bug in the caching logic of the KeyProperties. Method UpdateAsync() and DeleteAsync() alter the original cached list of properties key code ref.
So, if the first operation is a Update or Delete the "KeyPropertiesCache" return a pointer to the original list and the Update/Delete method add the explicitKeyProperties to the list. When the Insert() get called the "allPropertiesExceptKeyAndComputed" is wrong.

Test to reproduce it:

    public async Task TestMethod()
    {
        var myClass = new MyClass()
        {
            AccountId = Guid.NewGuid(),
            Name = "Some name"
        };

        using (IDbConnection db = new SqlConnection(connectionString))
        {
            //var x = await db.InsertAsync(myClass); // Add and test pass
            var t = await db.UpdateAsync(myClass);
            var r = await db.InsertAsync(myClass);                
        }
    }

Suggested fix that all returns from cache-layer (KeyPropertiesCache, ExplicitKeyPropertiesCache, ComputedPropertiesCache etc.) should call .ToList() on the item before return it.

Dapper.Contrib ArgumentException: Entity must have at least one [Key] or [ExplicitKey] property

Hi!
I'm getting exception during update

Dapper.Contrib.Extensions.SqlMapperExtensions.Update<T>(IDbConnection connection, T entityToUpdate, IDbTransaction transaction, Nullable<int> commandTimeout)
OptimoKasiarz.Data.Classes.SQL.UpdatePodatnik(string connectionString, Podatnicy pdt) in SQL.cs
con.Update(pdt);
OptimoKasiarz.Pages.Podatnik.EditModel+<OnPostAsync>d__39.MoveNext() in Edit.cshtml.cs
SQL.UpdatePodatnik(SQL.FirmaConnectionString, podatnik);
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod+<Convert>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod+<Execute>d__3.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker+<ExecuteHandlerMethod>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker+<ExecutePageWithPageModelAsync>d__19.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker+<InvokeInnerFilterAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

I put [Key] annotation to my class

    public class Podatnicy
    {
        [Key]
        public int PdT_PdTId { get; set; }
        public string PdT_Nazwa { get; set; }
        public string PdT_NIP { get; set; }
        public string PdT_Imie { get; set; }
        public string PdT_Nazwisko { get; set; }
        public string PdT_Miasto { get; set; }
        public string PdT_Ulica { get; set; }
        public string PdT_NrDomu { get; set; }
        public string PdT_NrLokalu { get; set; }
        public string PdT_KodPocztowy { get; set; }
        public string PdT_Wojewodztwo { get; set; }
        public string PdT_NrTel { get; set; }
        public string PdT_Email { get; set; }
        public string PdT_Uwagi { get; set; }
        public bool PdT_Aktywny { get; set; } = true;
        public int? PdT_UrZId { get; set; }
    }

and update function:

        public static void UpdatePodatnik(string connectionString, Podatnicy pdt)
        {
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                con.Open();
                con.Update(pdt);
            }
        }

What am I doing wrong?

Dapper.Contrib Update ignores mapping

Hi,

some fields in my table have underscores like full_name so i did
DefaultTypeMap.MatchNamesWithUnderscores = true;
which works just fine when i retrieve entity with Get<> but throws "Invalid column name 'FullName'."
when i update

my model

public class SmUser{
        public int Id { get; set; } 
        public string Name { get; set; }    
        public string FullName { get; set; }   
        public string Email { get; set; }        
    }

Whet i run Get it works just fine, the property FullName is populated with data
var user = cn.Get<SmUser>(id);

but when i update the entity

user.Email = user.Email + "z";
cn.Update(user);

i get
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
"Invalid column name 'FullName'."

and the sql query
update smuser set [Name] = @Name, [FullName] = @FullName, [Email] = @Email where [Id] = @Id

"FullName" is the entity property, "full_name" is the db field
using dapper 1.42

About Dapper Column Mapper Design ~ ^-^

hi ~
my database table design :

create table `users_orders` (
  `id` int(11) unsigned not null auto_increment,
  `users` int(11) not null,
  `orderno` varchar(32) not null,
  `normal_fee` decimal(10,2) null 
)

my object class :

  public class UserOrder: EntityByType
    { 
        [Column(Name = "id")]
        public  int Id { get; set; }
          
        [Column(Name = "users")] 
        public  int UserId { get; set; }
 
        [Column(Name = "orderno")]
        public string OrderNo { get; set; }
 
        [Column(Name = "normal_fee")]
        public  decimal NormalFee { get; set; }
          
 }

my class mapper :

       // TableName Mapper
       SqlMapperExtensions.TableNameMapper = (type) =>
            {
                var tableattr = type.GetCustomAttributes(false).SingleOrDefault(attr => attr.GetType().Name == "TableAttribute") as dynamic;
                if (tableattr != null)
                    return tableattr.Name;

                var name = type.Name;
                if (type.IsInterface && name.StartsWith("I"))
                    name = name.Substring(1);
                return name;
            };

    // Column Mapper
    SqlMapper.SetTypeMap(typeof(UserOrder), new CustomPropertyTypeMap(typeof(UserOrder), (type, columnName) => type.GetProperties()
                .FirstOrDefault(prop => prop.GetCustomAttributes(false).OfType<ColumnAttribute>()
                    .Any(attr => attr.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase)))));

it can query right , but update or insert not working

my update use 'Dapper.Contrib.Extensions'

public static bool Update<T>(this IDbConnection connection, T entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

error message:

Unknown column 'UserId'

Dapper.insert

public string AddItem(BASE_ITEMS Obj)
{
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ERPDEMO"].ConnectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
DynamicParameters ObjParm = new DynamicParameters();
try
{

                ObjParm.Add("@ItemCode", Obj.ItemCode);
                ObjParm.Add("@AdditionalCode", Obj.AdditionalCode);
                ObjParm.Add("@PartNumber", Obj.PartNumber);
                ObjParm.Add("@Name", Obj.Name);
                ObjParm.Add("@Description", Obj.Description);
                ObjParm.Add("@ItemTypeId", Obj.ItemTypeId);
                ObjParm.Add("@CategoryId", Obj.CategoryId);
                ObjParm.Add("@UserId", Obj.EntryUserId);
                ObjParm.Add("@newId", 0, DbType.Int32, direction: ParameterDirection.Output);
                ObjParm.Add("@errorId", 0, DbType.Int32, ParameterDirection.Output);
                connection.Execute("BASE_Item_Advanced_ADDYYY", ObjParm, commandType: CommandType.StoredProcedure);
                transaction.Commit();
               

            }
            catch (Exception e)
            {
                transaction.Rollback();
            }
            finally
            {
                connection.Close();
            }

System.InvalidOperationException was unhandled
Message=ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.
Source=System.Data
StackTrace:
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction, String sql, Action2 paramReader, Object obj, Nullable1 commandTimeout, Nullable1 commandType) in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Dapper\SqlMapper.cs:line 836 at CallSite.Target(Closure , CallSite , Type , IDbConnection , IDbTransaction , String , Object , Object , Nullable1 , Nullable1 ) at System.Dynamic.UpdateDelegates.UpdateAndExecute8[T0,T1,T2,T3,T4,T5,T6,T7,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) at CallSite.Target(Closure , CallSite , Type , IDbConnection , IDbTransaction , String , Object , Object , Nullable1 , Nullable1 ) at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable1 commandTimeout, Nullable`1 commandType) in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Dapper\SqlMapper.cs:line 176
at Dapper.Contrib.Extensions.SqlMapperExtensions.Insert[T](IDbConnection connection, T entityToInsert) in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Dapper\Extensions\SqlMapperExtensions.cs:line 175
at CodeSlice.Data.Profilers.ProfileInsert.b__2() in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Profilers\ProfileInsert.cs:line 51
at CodeSlice.Data.Profilers.ActionProfiler.Profile(String description, Action actionToProfile) in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Profilers\ActionProfiler.cs:line 16
at CodeSlice.Data.Profilers.ProfileInsert.Run() in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Profilers\ProfileInsert.cs:line 39
at CodeSlice.Data.Profilers.ProfileInsert.Exec() in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Profilers\ProfileInsert.cs:line 18
at CodeSlice.Data.Program.Main(String[] args) in C:\Projects\microorm-comparison\CodeSlice.Data\CodeSlice.Data\Program.cs:line 24
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

Insert return identity 0

I´m using dapper with mysql and .net and I need to insert and object and recovery the Id insert in this object. I´m using this:

int supplierId = db.Suppliers.Insert( supplier });

This is working in my computer but in the client computer it is returning "0", but the object is inserted in the table, there isn't any errors in the insert, the error is that doesn`t return the last id inserted.

I´m looking for information about insert but I can not find it. Always returns the last id inserted? Or do I have to make another query to consult the last id inserted?

Dapper.Contrib InsertAsync w/ mysql has problems with inserted ID (auto increment key column) and high concurrency

Using the latest MySQL driver 7.07-m61 without transactions I was running into issues where multiple inserts at the same time (on different MySQL connections but from the same pool) were getting the wrong (or no/0) values back for primary key auto increment integer columns. This was only an issue in high frequently inserts. By wrong I mean the insert ID for a different recently inserted item was assigned to another item.
This was with single inserts (not multiple in one call).
In theory last_insert_id should apple to the current connection however something is clearly amiss. I fixed this temporarily with a hack to use DBCommand .LastInsertedId (as on the exact command it can't miss) but not a great solution. Will be filing a feature request that may allow for lastinsertedid solution using the oncompleted feature.

Also this is not extremely high concurrency maybe only a 6-12 items in a second or two, but over a somewhat slow link which might exacerbate the problem. Could look at dual statement queries to do it in the insert query itself (like done in some other sql drivers) otherwise.

Contrib: Why is the id parameter of the Get method dynamic?

Is there any reason why the id parameter of the Get and GetAsync methods is a dynamic instead of a simple object? The only place where the parameter is used in the method is in a call to DynamicParameters.Add which just expects an object.

Although there is a small performance difference, my main intention here is clean code.

Dapper.Contrib - Allow custom ISqlAdapter

This is related to DapperLib/Dapper#336 - it would be useful if we could just plug in our own SqlAdapters in the Contrib project.

Use case - now that all the column names are quoted, column name case-insensitivity disappears in PostgreSQL (I think MySQL too). For some that may be good, others bad; rather than messing around decorating POCOs, just allow the ability to inject our own SqlAdapter.

For the fix for the above, it's just a matter of changing the AppendColumnNameand AppendColumnNameEqualsValue methods. But I have to fork the whole thing to do that. Others might want to plug in a more complex mapper.

It is possible to inject a GetDatabaseType custom callback, but it would be really useful too to have a GetDatabaseFormatter too.

Thank you.

Handling RowVersion for optimistic concurrency during update

Hi,

The database we are operating against uses optimistic concurrency via the MS SQL TIMESTAMP column type. This derails using Update without some complete faff of custom SQL to handle the situation.

I have forked the repo and done a first-pass implementation of supporting a new RowVersion attribute here: https://github.com/RaringCoder/Dapper

It is bundled in with some aesthetic changes, an update to how property caching works, and some code de-duplication.

The current implementation simply adds the version to the WHERE clause on update, resulting in nothing updated if the version differs. This does what I need, crudely. RowVersionAttribute can be applied to any columns, but so far I only support one. Column type doesn't matter. It is automatically excluded from inserts (possibly overridden by Write(true) if the database doesn't handle version for you?).

Before I go for a full PR, I want some advice on how better to handle a concurrency collision other than simply not updating any rows (the current implementation). My prevailing theory is something akin to how Insert currently works in that, per adaptor, we do a query to select any database-generated Ids. We could do something similar and select a flag out when checking if the version changed:

SELECT COUNT(1) AS VersionHasChanged FROM Table WHERE Key = @key AND Version <> @version

I will be using my fork locally to make progress on the app I'm working on, but I'd like to get this baked in to Contrib properly.

ExplicitKey value is occasionally null upon insert

Hey Guys!

Just wondering if you've experienced this issue before. We've been using dapper (1.50.0 now) for a while and it all works great but in the past couple of weeks we started seeing null values for explicit primary keys upon inserting objects. It happens randomly, sometimes for one insert but sometimes for all the inserts.

We added logging and the key property always has the value right before the insert but the insert still throws the primary key cannot be null exception. Recycling the app pool fixes it all the time so it might not be dapper related but something with the environment... still wondering if you've ever encountered something like this with Dapper.

Thank you in advance!

Rob

possibility to add custom adapter to Dapper.Contrib

Next step forward of #6
Please add this patch to Dapper.Contrib
0001-add-custom-AdapterDictionary.patch.zip
Dapper.Contrib with default adapter does not work at all for Oracle database.
I can make oracle adapter for insert with custom adapter but when I try to update record I will get error.

square brackets [ ] are not an edge symbols for column names in Oracle.

If you need I can provide adapter for Oracle and you can add it to standard distribution of Dapper.Contrib.

Exception in Dapper.Contrib SqlMapperExtension during the Insert "Value was either too large or too small for an Int32"

Scenario:
When explicitly inserting long value in primary key non identity column getting exception as "Value was either too large or too small for an Int32"

Method:
During the insert, the intermittent value stored in int and later i.e. before returning the value its being converted to long.

long Insert<T>(this IDbConnection connection, T entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null) where T : class

Please find the highlighted information.

capture

Could somebody help me on this.

StackTrace:
at System.Decimal.ToInt32(Decimal d)
at System.Decimal.op_Explicit(Decimal value)
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at SqlServerAdapter.Insert(IDbConnection connection, IDbTransaction transaction, Nullable1 commandTimeout, String tableName, String columnList, String parameterList, IEnumerable1 keyProperties, Object entityToInsert)
at Dapper.Contrib.Extensions.SqlMapperExtensions.Insert[T](IDbConnection connection, T entityToInsert, IDbTransaction transaction, Nullable`1 commandTimeout)

Get<T>()/Update() entity tracking changes and issues

In the description of public static T Get<T>(...) method it's said that

"Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension for optimal performance."

To check it I created an interface

public interface IInvoice
{
     string Code { get; set; }
     InvoiceDetail Detail { get; set; }
     [Key]
     int InvoiceID { get; set; }
     List<InvoiceItem> Items { get; set; }
     InvoiceKind Kind { get; set; }
}

for class Invoice : IInvoice and tried the next code:

using (var connection = ConnectionFactory())
{
     connection.Open();
     IInvoice invoice = connection.Get<IInvoice>(1);
     invoice.Code = "Bla bla bla";
     connection.Update(invoice);
}

First I got an exception

"Invalid cast from 'System.Int32 to InvoiceDetail." for which I've already made a pull-request.

After fixing it I got another exception at line 417 in SqlMapper.cs

System.NotSupportedException: 'The member Detail of type Z.Dapper.Examples.API.Dapper.Methods.InvoiceDetail cannot be used as a parameter value'

So, now the question is why does it check all the properties while I changed only one? Isn't it going to update them all?

Contrib : HasDefault, AllowNulls([True, False])

Hi guys,

How do you all feel about two more attributes being added to Contrib to handle database schemes that have "default values" and "allow nulls"?

There are two scenarios which we have come up against, which these two attributes should resolve.

  1. A database table has a column which has a default value.
  2. A database table has a column with allowNull set to false.

1a) Currently if you do an insert using a full model and the target table has a column with a default value (and the models value is null), Contrib has no way to know this and so will pass in a parameterized value instead. If this were an insert to a table, then the result would be 'null' and not the default set for the column. Even worse in the case where the target table has a default value and "Allow Null" is set to false. In this scenario, you get an exception because contrib is sending an explicit "null" which overrides SQL's default value.

If we apply a [HasDefault] attribute, and the scenario is an insert, it would be a trivial thing for Contrib to remove any values which are "null" and so removing it from the insert and allowing the database to apply its default.

2a) When a table column has "Allow Null" set to false, and the model has a null value set the update will run, again causing an exception on the connection. If we apply a [AllowNull(False)] or [NotNullable] attribute to the field we can let Contrib handle this issue before it gets put on the wire and sent over to SQL to error.

I'm happy to make a pull request for this work :)

Expand CommandDefinition.OnCompleted to pass the DBCommand (allow for items like mysql last insert id to be fetched easier)

There is OnCompleted currently which executes after a command is finished. It would be nice if we changed this handler to allow specifying a function to take the DbCommand itself.
This would be useful for things like MySQL which then have .LastInsertedId as part of the command available.

This is in part a possible fix to #63 to allow it to use lasterinsertedid. If this sounds like a good option I can generate a PR.

Insert/Update of interfaced type

Hello!
I'm found some error in Insert/Update operation if I pass interfaced type.

public int SaveAbstract(IObjectBase item)
{
    item._Updated = DateTime.UtcNow;
    if (item.ID > 0) c.Update(item, transaction: tr, commandTimeout: commandTimeout);
    else item.ID = (int)c.Insert(item, transaction: tr, commandTimeout: commandTimeout);
    cache.Remove(item.GetType().FullName.makeCacheKey());
    return item.ID;
}

Currently, Update and Insert method can't find table attribute on IObjectBase and substitute object class name. I'm start investigate and found some lines in this methods:
var type = typeof(T);

I think this line need to be replaced to entityToUpdate.GetType() because Insert/Update need to be know real type of passed item. After changes Insert/Update working correctly.

ArgumentOutOfRangeException in Firebird ADO Client dll when trying to insert string longer than 4000 characters

I'm getting this exception whenever I try to to Execute() any query with a string parameter that's longer than 4000 characters. Dapper is apparently passing -1 to the FbParameter class Size property setter and that is causing it to crash.

I've had to manually create the FbCommand and add the parameters for any query that uses fields of that size or higher. Is there any way to create the FbParameter manually when passing the created params object to Execute() or do I have to create the FbCommand manually every time until this can get fixed?

Dapper Contrib Insert Update not working

when i update dapper and contrib libs in to latest which is 1.50.4 Insert, Update throws exception. so i downgraded to Dapper in to 1.50.2 and Contrib in to 1.50.0 then works fine.

this is the exception that i'm getting

MySql.Data.MySqlClient.MySqlException (0x80004005): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1s () values ()' at
line 1 at MySql.Data.MySqlClient.MySqlStream.ReadPacket() at
MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow,
Int64& insertedId) at
MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean
force) at MySql.Data.MySqlClient.MySqlDataReader.NextResult() at
MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior
behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition&
command) in C:\projects\dapper\Dapper\SqlMapper.cs:line 552 at
Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param,
IDbTransaction transaction, Nullable1 commandTimeout, Nullable1
commandType) in C:\projects\dapper\Dapper\SqlMapper.cs:line 443 at
MySqlAdapter.Insert(IDbConnection connection, IDbTransaction
transaction, Nullable1 commandTimeout, String tableName, String columnList, String parameterList, IEnumerable1 keyProperties, Object
entityToInsert) in
C:\projects\dapper\Dapper.Contrib\SqlMapperExtensions.cs:line 897

at
Dapper.Contrib.Extensions.SqlMapperExtensions.Insert[T](IDbConnection
connection, T entityToInsert, IDbTransaction transaction, Nullable1 commandTimeout) in C:\projects\dapper\Dapper.Contrib\SqlMapperExtensions.cs:line 355
at RecruiterinsiderPortal.Data.AgencyRegionRepository.Save(Int32 userId, List`1 regions) in C:\Empite\RI\RecruiterinsiderPortal\RecruiterinsiderPortal\libs\RecruiterinsiderPortal.Data\AgencyRegionRepository.cs:line 67

StackOverflow

thanks

Remove reference type constraint from Contrib extension methods

Is there a reason why all Contrib extension methods have a constraint to reference types? The base Dapper extension methods don't have such constraints.

I agree that those generally make sense, but right now they prevent me from using Dapper Contrib because I need to implement a generic interface that doesn't specify any type constraints.

SQL logic error near ")": syntax error - with Contrib

Hi
I've noticed that when making superclass as DAL containing CRUD operation with SQLite it always give this error
the code is like that

public abstract class DataEntity : IDisposable
{ 
        public virtual void Insert()
        {
                using (var db = ConFactory.Connection)
                {
                    db.Open();
                    var tr = db.BeginTransaction();
                    db.Insert(this, tr);
                    tr.Commit();
                }
        }
}

and my classes looks like that

[Table("[test]")]
   public class Test : DataEntity
   {
       [Key]
       public int TestId { get; set; }

       public string Name { get; set; }
   }

using the code like this will result SQL logic error near ")": syntax error

using (Test t = new Test { Name = textBox2.Text })
{
     t.Insert();
     textBox1.Text = t.TestId.ToString();
 }

BUT when Insert method dragged to [Test] class it works perfectly

Contrib: Insert - No Return Value if trigger (instead of insert) on table

Hello together,

I'm aware that following scenario is maybe not a "typical" one, but at least for Dapper.Contrib 1.43 it had worked.

Scenario:
I've got a table which use a "trigger instead of insert as" and within also a merge function. So if the Insert does not exist, it will insert it, otherwise update it.

Issue
The Insert will happen, but I will always receive "0" as value. At least for the 1.50.x (0 and 2 tested) release. The 1.43 return the correct id.

Example
I've created a solution which contain two project (one with Contrib 1.50, one with 1.43) to show the scenario. It's available at https://github.com/Telaran/dapper_trigger_issue

I hope I've provided enough information.

Workaround
Currently I'm not sure which workaround would make more sense: Use 1.43 (I currently don't need any Core Compability) or use 1.50 and always after insert make a query to get the Id.

Table Attribute is being ignored

I've got a table and class name User, which is a keyword in SQL, so as per DapperLib/Dapper#398 I have used the table attribute as follows:

[Table("[User]")] 
public class User : IUser<int>  
{
  public int Id { get; set; }
  public string UserName { get; set; }
  public bool EmailConfirmed { get; set; }
  public string PasswordHash { get; set; }
  public DateTime? LockoutEndDateUtc { get; set; }
  public bool LockoutEnabled { get; set; }
  public int AccessFailedCount { get; set; }
}

And I'm attempting to insert records like so:

public async Task CreateAsync(User user)
{
  using (var connection = GetConnection())
  {
    await connection.InsertAsync(user);
  }
}

If it matters, this is for a Dapper implementation of the backend of ASP.NET Identity.

However, I'm seeing in SQL Server Profiler that I'm writing the SQL the bare "User" instead of my specified "[User]". Upon closer inspection, it seems SqlMapperExtensions.GetTableName(Type type) is the culprit, since it early returns if the type handle's name is available.

Am I missing something here?

Adding Dapper.Contrib Attributes to model carries dependency with Dapper library (and dapper.Contrib)

Hi,

I have been using dapper and dapper.contrib for years. Common use case is you have a project with your POCs. i.e. WhateverCompany.Model. Usual scenario is you expose "some" of this objects to the outside world, i.e. "Products" in the form of a package, so some contracts will carry the "Product" entity.

The problem comes when your customers need to add dapper dependency as it is required for attributes as "ComputedAttribute", "TableAttribute", etc. In few words, packaging the "Model" project will add "Dapper" and "Dapper.Contrib" packages which is not ideal, as you are only decorating one property with an attribute. I.e.:

[Computed]
public DateTime? EffectiveDate { get; set; }

I think it would be ideal if you would package these attributes in a smaller project, so there is not a dependency with the whole Dapper project, or else use reflection in a way that would allow to import (copy) these attributes to the own project, which actually works for the "TableAttribute" but not for the rest of them.

This way the Repo project would need this Dapper dependency, but the Model project and all the referencing clients wouldn't need to add this dependency to the projects.

Thanks

TimeSpan SqlLite

I use Dapper.Contrib with SqlLite and it does not work.

create table mytable (
    id integer primary key,
    duration text not null,
);
insert into mytable(duration) values ('0.01:00:00');

C# code

[Table("mytable")]
public class ClientTest
{
        public long Id { get; set; }
        public TimeSpan Duration { get; set; }
}

Got error:

System.Data.DataException: Error parsing column 4 (duration=0.01:00:00 - String)

When I write a TypeHandler:

public class TimeSpanHandler : SqlMapper.TypeHandler<TimeSpan>
{
    public override TimeSpan Parse(object value)
    {
        return TimeSpan.Parse((string)value);
    }

    public override void SetValue(IDbDataParameter parameter, TimeSpan value)
    {
        throw new InvalidOperationException("Never called!");
        //parameter.Value = value.ToString();
    }
}

Then it works fine for query and update, too. That's a mistake since SetValue is never called.

So we have a 2 bugs:

  1. TimeSpan for SqlLite does not work by default.
  2. TypeHandler is called just Parse, the SetValue is never called.

Insert with Nullable<int> Id gives "Invalid cast" error

Im Dapper.Contrib 1.50.0, when the model is defined with an Id of nullable int and the SQL Server database is an INT IDENTITY(1,1), the result of a Dapper.Contrib INSERT is:

Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.

Reproduction:

CREATE TABLE Car
(
    Id INT IDENTITY(1,1),
    Model VARCHAR(50)
)
public class Car
{
    public int? Id { get; private set; }
    public string Model { get; private set; }
}
var id = connection.Insert(new Car { Model = "Mazda" });

This was working in Dapper.Contrib 1.43 but is broken in Dapper.Contrib 1.50.0.

Dapper Contrib - doesnt insert into database unless all fields values are provided.

I am using Dapper Contrib to Insert values into table. The insert doesnt happen unless you provide all Entity property values.

Here is my entity:

[Table("Order")]
public class Order
{
    [Key]
    public int OrderId { get; set; }
    public int Quantity { get; set; }
    public decimal? Price { get; set; }
    public string PaymentType { get; set; }

}

Here is my Table

CREATE TABLE [dbo].[Order](
[OrderId] [int] IDENTITY(1,1) NOT NULL,
[Quantity] [int] NOT NULL,
[Price] [money] NULL,
[PaymentType] nvarchar NULL
)

Here PaymentType is nullable but unless i pass PaymentType as empty string in the code. dapper contrib doesnt make an insert to table.

Let me know if anyone has faced this.

`Insert` method always returns 0 when using [ExplicitKey].

If your table has a user generated key you need to generate the key property with the [ExplicitKey] attribute as per the Contrib docs. Example:

public class Employee
{
    [ExplicitKey]
    public int Id { get; set; }
    public string Name { get; set; }
    // etc etc etc
}

However the Dapper.Contrib Insert method always returns 0 meaning there is no (easy) way to determine whether or not the record was written successfully. Can you change this please so that the Id is returned to indicate success or 0 is returned for failure as it does when using a system generated key.

MySQL Insert does not return inserted ID if you do not open the connection first

The MySql Adapter in https://github.com/StackExchange/Dapper/blob/master/Dapper.Contrib/SqlMapperExtensions.Async.cs does not check for an open connection. Consequently, if a closed connection is used, the following two commands (lines 403 & 404) are issued on separate connections. This means that the "SELECT LAST_INSERT_ID()" command will return 0.

await connection.ExecuteAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
var r = await connection.QueryAsync<dynamic>("SELECT LAST_INSERT_ID() id", transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);

One could fix the issue by either checking the connection is open and opening it if it isnt. Or maybe use QueryAsync and concatenate the insert query and the select query into one call.

No way to exclude properties during an update

I understand that using Dapper.Contrib I can use the Write and Computed attributes to ignore properties during write operations. However, this will ignore the properties on both insert and update. I need a way to ignore properties on updates. My suggestion would be to add 2 attributes... perhaps named Insertable(bool) and Updateable(bool). When a false value is passed to these the framework would exclude that property for the given operation. This is a lightweight, straightforward approach to a very common problem.

Sysbase dapper.contrib support

I have a package for supporting sybase in dapper contrib. Currently work in our enviroment, how can I contribute to back to the community?

Missing Dapper.Contrib.StrongName

Hello,

I would like to use dapper and dapper.contrib with strongName but i have only strongname for dapper. how can i create pull request for this one (easy feature)

Dapper.Contrib does not pass Turkey Test

In the following code:

https://github.com/StackExchange/Dapper/blob/master/Dapper.Contrib/SqlMapperExtensions.cs#L117

There is a string.equals operation to find "id" in the all properties which fails in Turkey test. So operations are getting failed in all Turkish locale servers. "id" is "İD" or "ıd" in Turkish, so basically it fails for the "ID" column.

We have a custom "ToLower" extension which handles this issue. I don't know if there is another easy solution to work around.

Dapper error on insert record in Firebird

I'm writing a multidabase application with Firebird and PostgreSQL, using Dapper and ASP.NET MVC (migrating from EF). The C# statements to perform CRUD operations in the PGSQL database work fine. When migrating to Firebird, just changing the concrete connection object from NpgsqlConnection to FbConnection, I receive the following error message when trying to insert a record:

FirebirdSql.Data.FirebirdClient.FbException: Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 23 [ ---> FirebirdSql.Data.Common.IscException: Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 23

Then, I tried to isolated the problem, testing the insert statement with pure ADO.NET with FirebirdClient (this works fine):

con.Open();
var SQL = "INSERT INTO UNMEDIDA(CD_UNIDADE, NM_UNIDADE, DS_SIGLA)
           VALUES(@CD_UNIDADE, @NM_UNIDADE, @DS_SIGLA);";
var cmd = new FbCommand(SQL, con);
cmd.Parameters.AddWithValue("@CD_UNIDADE", 1);
cmd.Parameters.AddWithValue("@NM_UNIDADE", "AA");
cmd.Parameters.AddWithValue("@DS_SIGLA", "AA");
cmd.ExecuteNonQuery();
con.Close();

After, using Dapper without contrib, just the generic execute (this works fine too):

var SQL = "INSERT INTO UNMEDIDA(CD_UNIDADE, NM_UNIDADE, DS_SIGLA)
           VALUES(@CD_UNIDADE, @NM_UNIDADE, @DS_SIGLA);";
object obj = new { CD_UNIDADE = 1, NM_UNIDADE = "AA", DS_SIGLA = "AA" };
con.Execute(SQL, obj);

The error ocurrs when I try to use the generic Insert. Dapper will try to use reflection in to the mapping class to extract field names, to build dynamically a insert statament. Probably this statament generated by Dapper has a sintax error. The following code works with PG and Dapper, but fails with FB:

[Table("UNMEDIDA")]
public class UNMEDIDA
{
  [ExplicitKey]
  public int CD_UNIDADE { get; set; }
  public string NM_UNIDADE { get; set; }
  public string DS_SIGLA { get; set; }
}
...
UNMEDIDA obj = new UNMEDIDA { CD_UNIDADE = 1, NM_UNIDADE = "AA", DS_SIGLA = "AA" };
con.Insert(obj);

The code above works fine with Npgsql.

Seens like a error in parameters dynamic generation or something.

Dapper.Contrib "Insert" throws "Cannot convert null to 'int' because it is a non-nullable value type" when trying to call insert extension method while not using identity column at database

this is the issue. create a table in the database without identity column. create its poco class and try to call insert method.
I would like to set id column from my application. that is why i am not using identity column.

i fould the reason when i debug the code. After I call Insert extension method, it tries to return @@Identity value as integer. but because of id is not identity, it returns null. so i get "Cannot convert null to 'int' because it is a non-nullable value type" exception message.

CREATE TABLE User(
    [Id] [int] Primary key NOT NULL ,
    [Name] nvarchar(50) NOT NULL
)
public class User
{
 public Int32 Id {get;set;}
 public String Name {get;set;}
}

using Dapper.Contrib.Extensions;

var connStr = "bla bla";
var connection = new SqlConnection(connStr);
connection.Open();
connection.Insert(new User { Id = 1, Name="Tugbay" });
connection.Close();

dapper.contrib can insert <T> return the explicite key

Hello,

I am looking to do a generic function

T entity = InsertGet <T> (obj);

the principle is to make an insert and automatically return the created entity.

The principle would be to recover the object actually created in the database with all calculated fields ...

With Dapper and Dapper.Contrib it's super simple in 2 lines:

var id = await idb.InsertAsync (entityToInsert, trx);
return idb.Get <T> (id);

it works perfectly if [Key] is a numerique Id

but it is possible to define an "explicitkey" in a class

image

When performing an insert

var code = con.Insert<farticles> (art);

code contains the first field of the table (ART_SEQ) and not the "ExplicitKey" (ART_CODE)

would it be possible to make an insert that returns the "ExplicitKey" (ART_CODE) and not id because this id field does not exist...

or

is it possible to create the généric function directly it would be very convenient because it will simplify a lot of code

generic function => T entity = InsertGet <T> (obj);

and and the same for update

generic function => T entity = UpdateGet <T> (obj);

Thanks for your help

Dapper.Contrib when insert occurred "ORA-00928" for oracle

I have some problem for insert use Dapper.Contrib.I have class like below

public class Company
{
    public int Id { get; set; } = 1;
    public string CompanyName { get; set; }
}

My table like below picture
image

If i am using sql to insert that is ok.If i use insert to mssql also success but if i use oracle that is wrong.I want show code to below.If You need deep details that must tell me.

public class Company
{
    public int Id { get; set; } = 1;
    public string CompanyName { get; set; }
}

public IDbConnection GetConnection 
{
    get
    {
        string connString = "Data source=localhost/book;User id=C##ANSON;Password=1234;";
        var conn = new OracleConnection(connString);
        return conn;
    }
}

public async Task<IHttpActionResult> Post() 
{
    var companys = new List<Company>();
    for (int i = 0; i < 5; i++)
    {
        companys.Add(new Company
        {
            CompanyName = $"company{i}"
        });
    }
    using (TransactionScope scope = new TransactionScope()) 
    {
        using (var con = GetConnection) 
        {

            //con.Execute("insert into company (companyname) values (:companyname)", companys.Select(x => new CompanyDto { CompanyName = x.CompanyName }));
            //if use above that is success.but if use below that will occurred ORA-00928
            con.Insert(companys);
            scope.Complete();
            return Ok();
        }
    }
} 

Found one bug in Dapper.Contrib (1.50.0.0) while inserting an entity with long id value

In class Dapper.Contrib.Extensions.SqlMapperExtensions we found one bug as below -

Starting from line number 47 -

int num;
    if (!flag)
    {
        num = **formatter.Insert(**connection, transaction, commandTimeout, tableName, stringBuilder.ToString(), stringBuilder2.ToString(), list, entityToInsert);
    }
    else
    {
        string text = string.Format("insert into {0} ({1}) values ({2})", tableName, stringBuilder, stringBuilder2);
        num = SqlMapper.Execute(connection, text, entityToInsert, transaction, commandTimeout, null);
    }
    if (expr_121)
    {
        connection.Close();
    }
    return (long)num;

formatter.Insert is returning long but getting stored in int variable. This is a bug and must be fixed soon.

Dapper Snapshotter Updates "modified" Properties rather than "changed"

Instead of Full Change tracking simply knowing which properties have had their setters called since the object was were returned by a Dapper would be a great feature.

If you retrieve a fresh object from the database and explicitly set a property, no matter what it should be issuing an update statement for that column when persisted . Dapper Snapshotter only looks at "modified" properties, instead of "changed" properties, therefore it may or may not issue and update for the column depending on original value held in memory. This is usually fine if concurrent connections are not updating the same columns or performing pessimist locking, however it can cause issues like:
Client A fetches a column value of "Monday", Client B Updates the column to "Tuesday", then Client A sets the value on the object to "Monday" then performs an update, the outcome would be "Tuesday" even though Client A was last, this is because the Snapshotter thinks nothing has changed as the memory value is stale.

This causes unexpected results especially when implementing HTTP PUT requests that should replace the entire resource. A great explanation of this exists at: https://blog.jooq.org/2017/06/28/orms-should-update-changed-values-not-just-modified-ones/

Has anybody encountered any similar race conditions at scale? I was thinking of rolling my own Proxy implementation to keep track of calls made to setters as I can't see to find anything that suits my needs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.