diff --git a/ldap3_mapper_new/attribute.py b/ldap3_mapper_new/attribute.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b8376e4408a8cc6e781b08be050ed309f5822c3
--- /dev/null
+++ b/ldap3_mapper_new/attribute.py
@@ -0,0 +1,57 @@
+from collections.abc import MutableSequence
+
+class AttributeList(MutableSequence):
+	def __init__(self, ldap_object, name, aliases):
+		self.__ldap_object = ldap_object
+		self.__name = name
+		self.__aliases = [name] + aliases
+
+	def __get(self):
+		return list(self.__ldap_object.getattr(self.__name))
+
+	def __set(self, values):
+		for name in self.__aliases:
+			self.__ldap_object.setattr(name, values)
+
+	def __repr__(self):
+		return repr(self.__get())
+
+	def __setitem__(self, key, value):
+		tmp = self.__get()
+		tmp[key] = value
+		self.__set(tmp)
+
+	def __delitem__(self, key):
+		tmp = self.__get()
+		del tmp[key]
+		self.__set(tmp)
+
+	def __len__(self):
+		return len(self.__get())
+
+	def __getitem__(self, key):
+		return self.__get()[key]
+
+	def insert(self, index, value):
+		tmp = self.__get()
+		tmp.insert(index, value)
+		self.__set(tmp)
+
+class Attribute:
+	def __init__(self, name, aliases=None, multi=False):
+		self.name = name
+		self.aliases = aliases or []
+		self.multi = multi
+
+	def __get__(self, obj, objtype=None):
+		if obj is None:
+			return self
+		if self.multi:
+			return AttributeList(obj.ldap_object, self.name, self.aliases)
+		return obj.ldap_object.getattr(self.name)
+
+	def __set__(self, obj, values):
+		if not self.multi:
+			values = [values]
+		for name in self.aliases:
+			obj.ldap_object.setattr(name, values)
diff --git a/ldap3_mapper_new/model.py b/ldap3_mapper_new/model.py
index cf681be8bceb1913eb64a9a5507f5732fa23ecbc..8981899ff41ef726a5bb981f3cc217a3b9aa7771 100644
--- a/ldap3_mapper_new/model.py
+++ b/ldap3_mapper_new/model.py
@@ -1,6 +1,18 @@
-from collections.abc import MutableSet
 
-from ldap3.utils.conv import escape_filter_chars
+try:
+	# Added in v2.5
+	from ldap3.utils.dn import escape_rdn
+except ImportError:
+	# From ldap3 source code, Copyright Giovanni Cannata, LGPL v3 license
+	def escape_rdn(rdn):
+		# '/' must be handled first or the escape slashes will be escaped!
+		for char in ['\\', ',', '+', '"', '<', '>', ';', '=', '\x00']:
+			rdn = rdn.replace(char, '\\' + char)
+		if rdn[0] == '#' or rdn[0] == ' ':
+			rdn = ''.join(('\\', rdn))
+		if rdn[-1] == ' ':
+			rdn = ''.join((rdn[:-1], '\\ '))
+		return rdn
 
 from . import base
 
@@ -89,74 +101,10 @@ class Model:
 		values = self.ldap_object.getattr(self.ldap_dn_attribute)
 		if not values:
 			return None
-		return '%s=%s,%s'%(self.ldap_dn_attribute, escape_filter_chars(values[0]), self.ldap_dn_base)
+		return '%s=%s,%s'%(self.ldap_dn_attribute, escape_rdn(values[0]), self.ldap_dn_base)
 
 	def __repr__(self):
 		cls_name = '%s.%s'%(type(self).__module__, type(self).__name__)
 		if self.dn is not None:
 			return '<%s %s>'%(cls_name, self.dn)
 		return '<%s>'%cls_name
-
-class SetView(MutableSet):
-	def __init__(self, getitems, additem, delitem, encode=None, decode=None):
-		self.__getitems = getitems
-		self.__additem = additem
-		self.__delitem = delitem
-		self.__encode = encode or (lambda x: x)
-		self.__decode = decode or (lambda x: x)
-
-	def __repr__(self):
-		return repr(set(self))
-
-	def __contains__(self, value):
-		return value is not None and self.__encode(value) in self.__getitems()
-
-	def __iter__(self):
-		return iter(filter(lambda obj: obj is not None, map(self.__decode, self.__getitems())))
-
-	def __len__(self):
-		return len(set(self))
-
-	def add(self, value):
-		if value not in self:
-			self.__additem(self.__encode(value))
-
-	def discard(self, value):
-		self.__delitem(self.__encode(value))
-
-	def update(self, values):
-		for value in values:
-			self.add(value)
-
-class Attribute:
-	def __init__(self, name, multi=False, encode=None, decode=None, aliases=None):
-		self.name = name
-		self.multi = multi
-		self.encode = encode or (lambda x: x)
-		self.decode = decode or (lambda x: x)
-		self.aliases = [name] + (aliases or [])
-
-	def additem(self, obj, value):
-		for name in self.aliases:
-			obj.ldap_object.attradd(name, value)
-
-	def delitem(self, obj, value):
-		for name in self.aliases:
-			obj.ldap_object.attrdel(name, value)
-
-	def __get__(self, obj, objtype=None):
-		if obj is None:
-			return self
-		if self.multi:
-			return SetView(getitems=lambda: obj.ldap_object.getattr(self.name),
-			               additem=lambda value: self.additem(obj, value),
-			               delitem=lambda value: self.delitem(obj, value),
-			               encode=self.encode, decode=self.decode)
-		return self.decode((obj.ldap_object.getattr(self.name) or [None])[0])
-
-	def __set__(self, obj, values):
-		if not self.multi:
-			values = [values]
-		values = [self.encode(value) for value in values]
-		for name in self.aliases:
-			obj.ldap_object.setattr(name, values)