diff --git a/src/Volo.Abp/Volo/Abp/Domain/Entities/Entity.cs b/src/Volo.Abp/Volo/Abp/Domain/Entities/Entity.cs
new file mode 100644
index 0000000000..0273ba57b5
--- /dev/null
+++ b/src/Volo.Abp/Volo/Abp/Domain/Entities/Entity.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Volo.Abp.Domain.Entities
+{
+ //TODO: Think on Entity class without PK
+ /////
+ ///// A shortcut of for most used primary key type ().
+ /////
+ //public abstract class Entity : Entity, IEntity<>
+ //{
+
+ //}
+
+ ///
+ /// Basic implementation of IEntity interface.
+ /// An entity can inherit this class of directly implement to IEntity interface.
+ ///
+ /// Type of the primary key of the entity
+ public abstract class Entity : IEntity
+ {
+ ///
+ /// Unique identifier for this entity.
+ ///
+ public virtual TPrimaryKey Id { get; set; }
+
+ ///
+ /// Checks if this entity is transient (it has not an Id).
+ ///
+ /// True, if this entity is transient
+ public virtual bool IsTransient()
+ {
+ if (EqualityComparer.Default.Equals(Id, default(TPrimaryKey)))
+ {
+ return true;
+ }
+
+ //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext
+ if (typeof(TPrimaryKey) == typeof(int))
+ {
+ return Convert.ToInt32(Id) <= 0;
+ }
+
+ if (typeof(TPrimaryKey) == typeof(long))
+ {
+ return Convert.ToInt64(Id) <= 0;
+ }
+
+ return false;
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj == null || !(obj is Entity))
+ {
+ return false;
+ }
+
+ //Same instances must be considered as equal
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ //Transient objects are not considered as equal
+ var other = (Entity)obj;
+ if (IsTransient() && other.IsTransient())
+ {
+ return false;
+ }
+
+ //Must have a IS-A relation of types or must be same type
+ var typeOfThis = GetType().GetTypeInfo();
+ var typeOfOther = other.GetType().GetTypeInfo();
+ if (!typeOfThis.IsAssignableFrom(typeOfOther) && !typeOfOther.IsAssignableFrom(typeOfThis))
+ {
+ return false;
+ }
+
+ //TODO: How to handle this?
+ //if (this is IMayHaveTenant && other is IMayHaveTenant &&
+ // this.As().TenantId != other.As().TenantId)
+ //{
+ // return false;
+ //}
+
+ //if (this is IMustHaveTenant && other is IMustHaveTenant &&
+ // this.As().TenantId != other.As().TenantId)
+ //{
+ // return false;
+ //}
+
+ return Id.Equals(other.Id);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Id.GetHashCode();
+ }
+
+ ///
+ public static bool operator ==(Entity left, Entity right)
+ {
+ if (Equals(left, null))
+ {
+ return Equals(right, null);
+ }
+
+ return left.Equals(right);
+ }
+
+ ///
+ public static bool operator !=(Entity left, Entity right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return $"[{GetType().Name} {Id}]";
+ }
+ }
+}
diff --git a/src/Volo.Abp/Volo/Abp/Domain/Entities/IEntity.cs b/src/Volo.Abp/Volo/Abp/Domain/Entities/IEntity.cs
new file mode 100644
index 0000000000..309c810d2c
--- /dev/null
+++ b/src/Volo.Abp/Volo/Abp/Domain/Entities/IEntity.cs
@@ -0,0 +1,29 @@
+namespace Volo.Abp.Domain.Entities
+{
+ //TODO: Think on Entity class without PK
+ /////
+ ///// A shortcut of for most used primary key type ().
+ /////
+ //public interface IEntity : IEntity
+ //{
+
+ //}
+
+ ///
+ /// Defines interface for base entity type. All entities in the system must implement this interface.
+ ///
+ /// Type of the primary key of the entity
+ public interface IEntity
+ {
+ ///
+ /// Unique identifier for this entity.
+ ///
+ TPrimaryKey Id { get; set; }
+
+ ///
+ /// Checks if this entity is transient (not persisted to database and it has not an ).
+ ///
+ /// True, if this entity is transient
+ bool IsTransient();
+ }
+}
diff --git a/src/Volo.Abp/Volo/Abp/Domain/Values/ValueObject.cs b/src/Volo.Abp/Volo/Abp/Domain/Values/ValueObject.cs
new file mode 100644
index 0000000000..f271065f81
--- /dev/null
+++ b/src/Volo.Abp/Volo/Abp/Domain/Values/ValueObject.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Volo.Abp.Domain.Values
+{
+ //Inspired from https://blogs.msdn.microsoft.com/cesardelatorre/2011/06/06/implementing-a-value-object-base-class-supertype-patternddd-patterns-related/
+
+ ///
+ /// Base class for value objects.
+ ///
+ /// The type of the value object.
+ public abstract class ValueObject : IEquatable
+ where TValueObject : ValueObject
+ {
+ public bool Equals(TValueObject other)
+ {
+ if ((object)other == null)
+ {
+ return false;
+ }
+
+ var publicProperties = GetType().GetTypeInfo().GetProperties();
+ if (!publicProperties.Any())
+ {
+ return true;
+ }
+
+ return publicProperties.All(property => Equals(property.GetValue(this, null), property.GetValue(other, null)));
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+
+ var item = obj as ValueObject;
+ return (object)item != null && Equals((TValueObject)item);
+
+ }
+
+ public override int GetHashCode()
+ {
+ const int index = 1;
+ const int initialHasCode = 31;
+
+ var publicProperties = GetType().GetTypeInfo().GetProperties();
+
+ if (!publicProperties.Any())
+ {
+ return initialHasCode;
+ }
+
+ var hashCode = initialHasCode;
+ var changeMultiplier = false;
+
+ foreach (var property in publicProperties)
+ {
+ var value = property.GetValue(this, null);
+
+ if (value == null)
+ {
+ //support {"a",null,null,"a"} != {null,"a","a",null}
+ hashCode = hashCode ^ (index * 13);
+ continue;
+ }
+
+ hashCode = hashCode * (changeMultiplier ? 59 : 114) + value.GetHashCode();
+ changeMultiplier = !changeMultiplier;
+ }
+
+ return hashCode;
+ }
+
+ public static bool operator ==(ValueObject x, ValueObject y)
+ {
+ if (ReferenceEquals(x, y))
+ {
+ return true;
+ }
+
+ if (((object)x == null) || ((object)y == null))
+ {
+ return false;
+ }
+
+ return x.Equals(y);
+ }
+
+ public static bool operator !=(ValueObject x, ValueObject y)
+ {
+ return !(x == y);
+ }
+ }
+}