5 // Copyright (c) 2007-2008 Jiri Moudry, Stefan Klinger
\r
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
\r
8 // of this software and associated documentation files (the "Software"), to deal
\r
9 // in the Software without restriction, including without limitation the rights
\r
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
11 // copies of the Software, and to permit persons to whom the Software is
\r
12 // furnished to do so, subject to the following conditions:
\r
14 // The above copyright notice and this permission notice shall be included in
\r
15 // all copies or substantial portions of the Software.
\r
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\r
29 default namespace = "http://schemas.microsoft.com/linqtosql/mapping/2007"
\r
32 start = element Database { Database }
\r
35 element Table { Table }*,
\r
36 element Function { Function }*,
\r
37 attribute Name { text }?,
\r
38 attribute Provider { text }?
\r
42 element Type { Type },
\r
43 attribute Name { text }?,
\r
44 attribute Member { text }?
\r
49 element Column { Column }* |
\r
50 element Association { Association }*
\r
52 element Type { Type }*,
\r
53 attribute Name { text },
\r
54 attribute InheritanceCode { text }?,
\r
55 attribute IsInheritanceDefault { boolean }?
\r
59 attribute Name { text }?,
\r
60 attribute Member { text },
\r
61 attribute Storage { text }?,
\r
62 attribute DbType { text }?,
\r
63 attribute IsPrimaryKey { boolean }?,
\r
64 attribute IsDbGenerated { boolean }?,
\r
65 attribute CanBeNull { boolean }?,
\r
66 attribute UpdateCheck { UpdateCheck }?,
\r
67 attribute IsDiscriminator { boolean }?,
\r
68 attribute Expression { text }?,
\r
69 attribute IsVersion { boolean }?,
\r
70 attribute AutoSync { AutoSync}?
\r
74 attribute Name { text }?,
\r
75 attribute Member { text },
\r
76 attribute Storage { text }?,
\r
77 attribute ThisKey { text }?,
\r
78 attribute OtherKey { text }?,
\r
79 attribute IsForeignKey { boolean }?,
\r
80 attribute IsUnique { boolean }?,
\r
81 attribute DeleteRule { text }?,
\r
82 attribute DeleteOnNull { boolean }?
\r
86 element Parameter { Parameter }*,
\r
88 element ElementType { Type }* |
\r
89 element Return { Return }
\r
91 attribute Name { text }?,
\r
92 attribute Method { text },
\r
93 attribute IsComposable { boolean }?
\r
97 attribute Name { text }?,
\r
98 attribute Parameter { text },
\r
99 attribute DbType { text }?,
\r
100 attribute Direction { ParameterDirection }?
\r
103 Return = attribute DbType { text}?
\r
105 UpdateCheck = "Always" | "Never" | "WhenChanged"
\r
106 ParameterDirection = "In" | "Out" | "InOut"
\r
107 AutoSync = "Never" | "OnInsert" | "OnUpdate" | "Always" | "Default"
\r
110 ---------------- */
\r
114 using System.Collections.Generic;
\r
115 using System.Collections.ObjectModel;
\r
118 using System.Reflection;
\r
121 using DbLinq.Schema.Dbml;
\r
125 namespace System.Data.Linq.Mapping
\r
127 namespace DbLinq.Data.Linq.Mapping
\r
130 public sealed class XmlMappingSource : System.Data.Linq.Mapping.MappingSource
\r
134 XmlMappingSource(XmlReader reader)
\r
136 db = new DbmlDatabase(reader);
\r
139 public static XmlMappingSource FromReader(XmlReader reader)
\r
141 return new XmlMappingSource(reader);
\r
144 public static XmlMappingSource FromStream(Stream stream)
\r
146 return FromReader(XmlReader.Create(stream));
\r
149 public static XmlMappingSource FromUrl(string url)
\r
151 return FromReader(XmlReader.Create(url));
\r
154 public static XmlMappingSource FromXml(string xml)
\r
156 return FromReader(XmlReader.Create(new StringReader(xml)));
\r
159 protected override System.Data.Linq.Mapping.MetaModel CreateModel(System.Type dataContextType)
\r
161 return new XmlMetaModel(this, db, dataContextType);
\r
165 abstract class DbmlItem
\r
167 public const string DbmlNamespace = "http://schemas.microsoft.com/linqtosql/mapping/2007";
\r
169 public void ReadEmptyContent(XmlReader r, string name)
\r
171 if (r.IsEmptyElement)
\r
172 r.ReadStartElement(name, DbmlNamespace);
\r
175 r.ReadStartElement(name, DbmlNamespace);
\r
176 for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
\r
178 if (r.NamespaceURI != DbmlNamespace)
\r
180 throw UnexpectedItemError(r);
\r
182 r.ReadEndElement();
\r
185 public bool GetBooleanAttribute(XmlReader r, string attributeName)
\r
187 return r.GetAttribute(attributeName) == "true";
\r
189 public UpdateCheck GetUpdateCheckAttribute(XmlReader r, string attributeName)
\r
191 var s = r.GetAttribute(attributeName);
\r
192 return s != null ? (UpdateCheck)Enum.Parse(typeof(UpdateCheck), s) : default(UpdateCheck);
\r
194 public AutoSync GetAutoSyncAttribute(XmlReader r, string attributeName)
\r
196 var s = r.GetAttribute(attributeName);
\r
197 return s != null ? (AutoSync)Enum.Parse(typeof(AutoSync), s) : default(AutoSync);
\r
199 public T GetEnumAttribute<T>(XmlReader r, string attributeName)
\r
201 var s = r.GetAttribute(attributeName);
\r
202 return s != null ? (T)Enum.Parse(typeof(T), s) : default(T);
\r
204 public XmlException UnexpectedItemError(XmlReader r)
\r
206 return new XmlException(String.Format("Unexpected dbml element '{0}'", r.LocalName));
\r
209 class DbmlDatabase : DbmlItem
\r
211 public string Name;
\r
212 public string Provider;
\r
213 public List<DbmlTable> Tables = new List<DbmlTable>();
\r
214 public List<DbmlFunction> Functions = new List<DbmlFunction>();
\r
216 public DbmlDatabase(XmlReader r)
\r
219 Name = r.GetAttribute("Name");
\r
220 Provider = r.GetAttribute("Provider");
\r
221 if (r.IsEmptyElement)
\r
222 r.ReadStartElement("Database", DbmlNamespace);
\r
225 r.ReadStartElement("Database", DbmlNamespace);
\r
226 for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
\r
228 if (r.NamespaceURI != DbmlNamespace)
\r
232 switch (r.LocalName)
\r
235 Tables.Add(new DbmlTable(r));
\r
238 Functions.Add(new DbmlFunction(r));
\r
241 throw UnexpectedItemError(r);
\r
245 r.ReadEndElement();
\r
249 class DbmlTable : DbmlItem
\r
251 public DbmlType Type;
\r
252 public string Name;
\r
253 public string Member;
\r
255 public DbmlTable(XmlReader r)
\r
257 Name = r.GetAttribute("Name");
\r
258 Member = r.GetAttribute("Member");
\r
259 if (r.IsEmptyElement)
\r
260 r.ReadStartElement("Table", DbmlNamespace);
\r
263 r.ReadStartElement("Table", DbmlNamespace);
\r
264 for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
\r
266 if (r.NamespaceURI != DbmlNamespace)
\r
270 switch (r.LocalName)
\r
273 Type = new DbmlType(r);
\r
276 throw UnexpectedItemError(r);
\r
280 r.ReadEndElement();
\r
284 class DbmlType : DbmlItem
\r
286 public List<DbmlColumn> Columns = new List<DbmlColumn>();
\r
287 public List<DbmlAssociation> Associations = new List<DbmlAssociation>();
\r
288 public List<DbmlType> Types = new List<DbmlType>();
\r
289 public string Name;
\r
290 public string InheritanceCode;
\r
291 public bool IsInheritanceDefault;
\r
293 public DbmlType(XmlReader r)
\r
295 Name = r.GetAttribute("Name");
\r
296 InheritanceCode = r.GetAttribute("InheritanceCode");
\r
297 IsInheritanceDefault = GetBooleanAttribute(r, "IsInheritanceDefault");
\r
298 if (r.IsEmptyElement)
\r
299 r.ReadStartElement("Type", DbmlNamespace);
\r
302 r.ReadStartElement("Type", DbmlNamespace);
\r
303 for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
\r
305 if (r.NamespaceURI != DbmlNamespace)
\r
309 switch (r.LocalName)
\r
312 Columns.Add(new DbmlColumn(r));
\r
314 case "Association":
\r
315 Associations.Add(new DbmlAssociation(r));
\r
318 Types.Add(new DbmlType(r));
\r
321 throw UnexpectedItemError(r);
\r
325 r.ReadEndElement();
\r
330 class DbmlMemberBase : DbmlItem
\r
332 public string Name;
\r
333 public string Member;
\r
334 public string Storage;
\r
337 class DbmlColumn : DbmlMemberBase
\r
339 public string DbType;
\r
340 public bool IsPrimaryKey;
\r
341 public bool IsDbGenerated;
\r
342 public bool CanBeNull;
\r
343 public System.Data.Linq.Mapping.UpdateCheck UpdateCheck;
\r
344 public bool IsDiscriminator;
\r
345 public string Expression;
\r
346 public bool IsVersion;
\r
347 public System.Data.Linq.Mapping.AutoSync AutoSync;
\r
349 public DbmlColumn(XmlReader r)
\r
351 Member = r.GetAttribute("Member");
\r
352 Name = r.GetAttribute("Name") ?? Member;
\r
353 Storage = r.GetAttribute("Storage");
\r
354 DbType = r.GetAttribute("DbType");
\r
355 IsPrimaryKey = GetBooleanAttribute(r, "IsPrimaryKey");
\r
356 IsDbGenerated = GetBooleanAttribute(r, "IsDbGenerated");
\r
357 CanBeNull = GetBooleanAttribute(r, "CanBeNull");
\r
358 UpdateCheck = GetEnumAttribute<System.Data.Linq.Mapping.UpdateCheck>(r, "UpdateCheck");
\r
359 IsDiscriminator = GetBooleanAttribute(r, "IsDiscriminator");
\r
360 Expression = r.GetAttribute("Expression");
\r
361 IsVersion = GetBooleanAttribute(r, "IsVersion");
\r
362 AutoSync = GetEnumAttribute<System.Data.Linq.Mapping.AutoSync>(r, "AutoSync");
\r
363 ReadEmptyContent(r, "Column");
\r
366 class DbmlAssociation : DbmlMemberBase
\r
368 public string ThisKey;
\r
369 public string OtherKey;
\r
370 public bool IsForeignKey;
\r
371 public bool IsUnique;
\r
372 public string DeleteRule;
\r
373 public bool DeleteOnNull;
\r
375 public DbmlAssociation(XmlReader r)
\r
377 Name = r.GetAttribute("Name");
\r
378 Member = r.GetAttribute("Member");
\r
379 Storage = r.GetAttribute("Storage");
\r
380 ThisKey = r.GetAttribute("ThisKey");
\r
381 OtherKey = r.GetAttribute("OtherKey");
\r
382 IsForeignKey = GetBooleanAttribute(r, "IsForeignKey");
\r
383 IsUnique = GetBooleanAttribute(r, "IsUnique");
\r
384 DeleteRule = r.GetAttribute("DeleteRule");
\r
385 DeleteOnNull = GetBooleanAttribute(r, "DeleteOnNull");
\r
386 ReadEmptyContent(r, "Association");
\r
389 class DbmlFunction : DbmlItem
\r
391 public string Name;
\r
392 public string Method;
\r
393 public bool IsComposable;
\r
394 public List<DbmlParameter> Parameters = new List<DbmlParameter>();
\r
395 public List<DbmlType> ElementTypes = new List<DbmlType>();
\r
396 public DbmlReturn Return;
\r
398 public DbmlFunction(XmlReader r)
\r
400 Name = r.GetAttribute("Name");
\r
401 Method = r.GetAttribute("Method");
\r
402 IsComposable = GetBooleanAttribute(r, "IsComposable");
\r
403 if (r.IsEmptyElement)
\r
404 r.ReadStartElement("Function", DbmlNamespace);
\r
407 r.ReadStartElement("Function", DbmlNamespace);
\r
408 for (r.MoveToContent(); r.NodeType != XmlNodeType.EndElement; r.MoveToContent())
\r
410 if (r.NamespaceURI != DbmlNamespace)
\r
414 switch (r.LocalName)
\r
417 Parameters.Add(new DbmlParameter(r));
\r
419 case "ElementType":
\r
420 ElementTypes.Add(new DbmlType(r));
\r
423 Return = new DbmlReturn(r);
\r
426 throw UnexpectedItemError(r);
\r
430 r.ReadEndElement();
\r
434 class DbmlParameter : DbmlItem
\r
436 public string Name;
\r
437 public string Parameter;
\r
438 public string DbType;
\r
439 public ParameterDirection Direction;
\r
441 public DbmlParameter(XmlReader r)
\r
443 Name = r.GetAttribute("Name");
\r
444 Parameter = r.GetAttribute("Parameter");
\r
445 DbType = r.GetAttribute("DbType");
\r
446 Direction = GetEnumAttribute<ParameterDirection>(r, "Direction");
\r
447 ReadEmptyContent(r, "Parameter");
\r
450 class DbmlReturn : DbmlItem
\r
452 public string DbType;
\r
454 public DbmlReturn(XmlReader r)
\r
456 DbType = r.GetAttribute("DbType");
\r
457 ReadEmptyContent(r, "Return");
\r
461 class XmlMetaModel : System.Data.Linq.Mapping.MetaModel
\r
463 System.Data.Linq.Mapping.MappingSource source;
\r
465 System.Type context_type;
\r
466 System.Data.Linq.Mapping.MetaFunction[] functions;
\r
467 System.Data.Linq.Mapping.MetaTable[] tables;
\r
468 Dictionary<System.Type, XmlMetaType> types;
\r
470 public XmlMetaModel(System.Data.Linq.Mapping.MappingSource source, DbmlDatabase database, System.Type contextType)
\r
472 this.source = source;
\r
474 this.context_type = contextType;
\r
478 void RegisterTypes()
\r
480 types = new Dictionary<System.Type, XmlMetaType>();
\r
481 foreach (var t in d.Tables)
\r
482 RegisterTypeAndDescendants(t.Type);
\r
485 void RegisterTypeAndDescendants(DbmlType dt)
\r
488 System.Type t = GetTypeFromName(dt.Name);
\r
490 throw new ArgumentException(String.Format("type '{0}' not found", dt.Name));
\r
491 if (types.ContainsKey(t))
\r
493 types.Add(t, new XmlMetaType(this, dt));
\r
494 foreach (var cdt in dt.Types)
\r
495 RegisterTypeAndDescendants(cdt);
\r
498 public override System.Type ContextType
\r
500 get { return context_type; }
\r
503 public override string DatabaseName
\r
505 get { return d.Name; }
\r
508 public override System.Data.Linq.Mapping.MappingSource MappingSource
\r
510 get { return source; }
\r
513 public override System.Type ProviderType
\r
515 get { return GetTypeFromName(d.Provider); }
\r
518 public override System.Data.Linq.Mapping.MetaFunction GetFunction(MethodInfo method)
\r
520 foreach (var f in GetFunctions())
\r
521 if (f.Method == method)
\r
523 throw new ArgumentException(String.Format("Corresponding MetaFunction for method '{0}' was not found", method));
\r
526 public override IEnumerable<System.Data.Linq.Mapping.MetaFunction> GetFunctions()
\r
528 if (functions == null)
\r
530 var l = new List<System.Data.Linq.Mapping.MetaFunction>();
\r
531 foreach (var f in d.Functions)
\r
532 l.Add(new XmlMetaFunction(this, f));
\r
533 functions = l.ToArray();
\r
538 public System.Type GetTypeFromName(string name)
\r
540 string ns = context_type.Namespace;
\r
541 string full = !name.Contains('.') && !String.IsNullOrEmpty(ns) ? String.Concat(ns, ".", name) : name;
\r
542 var t = this.context_type.Assembly.GetType(full) ?? System.Type.GetType(full);
\r
544 throw new ArgumentException(String.Format("Type '{0}' was not found", full));
\r
548 public override System.Data.Linq.Mapping.MetaType GetMetaType(System.Type type)
\r
550 if (!types.ContainsKey(type))
\r
551 throw new ArgumentException(String.Format("Type '{0}' is not found in the mapping", type));
\r
552 return types[type];
\r
555 public override System.Data.Linq.Mapping.MetaTable GetTable(System.Type rowType)
\r
557 foreach (var t in GetTables())
\r
558 if (t.RowType.Type == rowType)
\r
560 //throw new ArgumentException(String.Format("Corresponding MetaTable for row type '{0}' was not found", rowType));
\r
564 public override IEnumerable<System.Data.Linq.Mapping.MetaTable> GetTables()
\r
566 if (tables == null)
\r
568 var l = new List<System.Data.Linq.Mapping.MetaTable>();
\r
569 foreach (var t in d.Tables)
\r
570 l.Add(new XmlMetaTable(this, t));
\r
571 tables = l.ToArray();
\r
577 class XmlMetaParameter : System.Data.Linq.Mapping.MetaParameter
\r
579 string dbtype, mapped_name;
\r
582 public XmlMetaParameter(DbmlParameter p, ParameterInfo parameterInfo)
\r
583 : this(p.DbType, p.Parameter, parameterInfo)
\r
587 public XmlMetaParameter(string dbType, string mappedName, ParameterInfo parameterInfo)
\r
589 this.dbtype = dbType;
\r
590 this.mapped_name = mappedName;
\r
591 this.pi = parameterInfo;
\r
594 public override string DbType { get { return dbtype; } }
\r
595 public override string MappedName { get { return mapped_name; } }
\r
596 public override string Name { get { return Parameter.Name; } }
\r
597 public override ParameterInfo Parameter { get { return pi; } }
\r
598 public override System.Type ParameterType { get { return pi.ParameterType; } }
\r
601 class XmlMetaTable : System.Data.Linq.Mapping.MetaTable
\r
603 public XmlMetaTable(XmlMetaModel model, DbmlTable table)
\r
605 this.model = model;
\r
608 if (t.Member != null)
\r
610 foreach (var member in model.ContextType.GetMember(t.Member))
\r
612 if (table_member != null)
\r
613 throw new ArgumentException(String.Format("The context type '{0}' contains non-identical member '{1}'", model.ContextType, t.Member));
\r
614 table_member = member;
\r
616 if (table_member == null)
\r
617 table_member = GetFieldsAndProperties(model.ContextType).First(pi => pi.GetMemberType().IsGenericType &&
\r
618 pi.GetMemberType().GetGenericTypeDefinition() == typeof(Table<>) &&
\r
619 pi.GetMemberType().GetGenericArguments()[0] == model.GetTypeFromName(t.Type.Name));
\r
620 if (table_member == null)
\r
621 throw new ArgumentException(String.Format("The context type '{0}' does not contain member '{1}' which is specified in dbml", model.ContextType, t.Member));
\r
622 member_type = table_member.GetMemberType();
\r
623 if (member_type.GetGenericTypeDefinition() != typeof(Table<>))
\r
624 throw new ArgumentException(String.Format("The table member type was unexpected: '{0}'", member_type));
\r
625 rt = member_type.GetGenericArguments()[0];
\r
629 rt = System.Type.GetType(t.Type.Name);
\r
631 row_type = model.GetMetaType(rt);
\r
632 if (row_type == null)
\r
633 throw new ArgumentException(String.Format("MetaType for '{0}' was not found", rt));
\r
635 static IEnumerable<MemberInfo> GetFieldsAndProperties(System.Type type)
\r
637 foreach (var f in type.GetFields())
\r
639 foreach (var p in type.GetProperties())
\r
643 XmlMetaModel model;
\r
645 MemberInfo table_member;
\r
646 System.Type member_type;
\r
647 System.Data.Linq.Mapping.MetaType row_type;
\r
650 public override MethodInfo DeleteMethod
\r
652 get { throw new NotImplementedException(); }
\r
655 public override MethodInfo InsertMethod
\r
657 get { throw new NotImplementedException(); }
\r
659 public override System.Data.Linq.Mapping.MetaModel Model { get { return model; } }
\r
660 public override System.Data.Linq.Mapping.MetaType RowType { get { return row_type; } }
\r
661 System.Type MemberType { get { return member_type; } }
\r
662 public override string TableName { get { return t.Name; } }
\r
664 public override MethodInfo UpdateMethod
\r
666 get { throw new NotImplementedException(); }
\r
670 MethodInfo GetMethod(TableFunction f)
\r
674 foreach (var mf in model.GetFunctions())
\r
675 if (mf.Name == f.FunctionId)
\r
681 class XmlMetaType : System.Data.Linq.Mapping.MetaType
\r
683 XmlMetaModel model;
\r
685 ReadOnlyCollection<System.Data.Linq.Mapping.MetaAssociation> associations;
\r
686 System.Type runtime_type;
\r
687 ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> members, identity_members, persistent_members;
\r
689 public XmlMetaType(XmlMetaModel model, DbmlType type)
\r
691 this.model = model;
\r
693 runtime_type = model.GetTypeFromName(t.Name);
\r
695 var l = new List<System.Data.Linq.Mapping.MetaDataMember>();
\r
696 l.AddRange(Array.ConvertAll<DbmlColumn, System.Data.Linq.Mapping.MetaDataMember>(
\r
697 t.Columns.ToArray(), c => new XmlColumnMetaDataMember(model, this, c, i++)));
\r
698 members = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember>(l);
\r
701 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaAssociation> Associations
\r
705 if (associations == null)
\r
707 var l = new List<System.Data.Linq.Mapping.MetaAssociation>();
\r
709 foreach (var a in t.Associations)
\r
710 l.Add(new XmlMetaAssociation(this, new XmlAssociationMetaDataMember(model, this, a, -1), a));
\r
711 associations = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaAssociation>(l.ToArray());
\r
713 return associations;
\r
716 public override bool CanInstantiate { get { return !runtime_type.IsAbstract; } }
\r
717 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> DataMembers { get { return members; } }
\r
718 public override System.Data.Linq.Mapping.MetaDataMember DBGeneratedIdentityMember
\r
720 get { return members.First(m => m.IsDbGenerated && m.IsPrimaryKey); }
\r
723 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaType> DerivedTypes
\r
725 get { throw new NotImplementedException(); }
\r
727 public override System.Data.Linq.Mapping.MetaDataMember Discriminator
\r
729 get { return members.First(m => m.IsDiscriminator); }
\r
731 public override bool HasAnyLoadMethod
\r
733 get { return members.Any(m => m.LoadMethod != null); }
\r
736 public override bool HasAnyValidateMethod
\r
738 get { throw new NotImplementedException(); }
\r
741 public override bool HasInheritance
\r
743 get { throw new NotImplementedException(); }
\r
745 public override bool HasInheritanceCode
\r
747 get { return t.InheritanceCode != null; }
\r
749 public override bool HasUpdateCheck { get { return members.Any(m => m.UpdateCheck != System.Data.Linq.Mapping.UpdateCheck.Never); } }
\r
750 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> IdentityMembers
\r
754 if (identity_members == null)
\r
756 identity_members = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember>(
\r
757 members.TakeWhile(m => m.IsPrimaryKey).ToArray());
\r
759 return identity_members;
\r
763 public override System.Data.Linq.Mapping.MetaType InheritanceBase
\r
765 get { throw new NotImplementedException(); }
\r
767 public override Object InheritanceCode { get { return t.InheritanceCode; } }
\r
769 public override System.Data.Linq.Mapping.MetaType InheritanceDefault
\r
771 get { throw new NotImplementedException(); }
\r
774 public override System.Data.Linq.Mapping.MetaType InheritanceRoot
\r
776 get { throw new NotImplementedException(); }
\r
779 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaType> InheritanceTypes
\r
781 get { throw new NotImplementedException(); }
\r
784 public override bool IsEntity { get { return true; } }
\r
785 public override bool IsInheritanceDefault { get { return t.IsInheritanceDefault; } }
\r
786 public override System.Data.Linq.Mapping.MetaModel Model { get { return model; } }
\r
787 public override string Name { get { return t.Name; } }
\r
789 public override MethodInfo OnLoadedMethod
\r
791 get { throw new NotImplementedException(); }
\r
794 public override MethodInfo OnValidateMethod
\r
796 get { throw new NotImplementedException(); }
\r
798 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> PersistentDataMembers
\r
802 if (persistent_members == null)
\r
804 persistent_members = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember>(
\r
805 members.TakeWhile(m => m.IsPersistent).ToArray());
\r
807 return persistent_members;
\r
810 public override System.Data.Linq.Mapping.MetaTable Table { get { return model.GetTable(runtime_type); } }
\r
811 public override System.Type Type { get { return runtime_type; } }
\r
812 public override System.Data.Linq.Mapping.MetaDataMember VersionMember { get { return members.First(m => m.IsVersion); } }
\r
814 public override System.Data.Linq.Mapping.MetaDataMember GetDataMember(MemberInfo member)
\r
816 //return members.First(m => m.Member == member);
\r
817 foreach (var m in members)
\r
818 if (m.Member == member || (m.Member.ToString() == member.ToString() && member.DeclaringType.IsAssignableFrom(m.Member.DeclaringType)))
\r
820 throw new ArgumentException(String.Format("No corresponding metadata member for '{0}'", member));
\r
823 public override System.Data.Linq.Mapping.MetaType GetInheritanceType(System.Type type)
\r
825 return InheritanceTypes.First(t => t.Type == type);
\r
829 public override System.Data.Linq.Mapping.MetaType GetTypeForInheritanceCode(object code)
\r
831 throw new NotImplementedException();
\r
835 class XmlMetaAssociation : System.Data.Linq.Mapping.MetaAssociation
\r
837 //XmlMetaType owner;
\r
839 ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> these_keys, other_keys;
\r
840 System.Data.Linq.Mapping.MetaDataMember member;
\r
842 public XmlMetaAssociation(XmlMetaType owner, XmlMetaDataMember member, DbmlAssociation a)
\r
844 //this.owner = owner;
\r
845 this.member = member;
\r
847 SetupRelationship();
\r
851 /// This function sets up the relationship information based on the attribute <see cref="XmlMetaModel"/>.
\r
853 private void SetupRelationship()
\r
855 //Get the association target type
\r
856 System.Type targetType = member.Member.GetFirstInnerReturnType();
\r
858 var metaModel = ThisMember.DeclaringType.Model as XmlMetaModel;
\r
859 if (metaModel == null)
\r
861 throw new InvalidOperationException("Internal Error: MetaModel is not a XmlMetaModel");
\r
864 System.Data.Linq.Mapping.MetaTable otherTable = metaModel.GetTable(targetType);
\r
867 these_keys = GetKeys(a.ThisKey ?? String.Empty, ThisMember.DeclaringType);
\r
870 other_keys = GetKeys(a.OtherKey ?? String.Empty, otherTable.RowType);
\r
873 //Seperator used for key lists
\r
874 private static readonly char[] STRING_SEPERATOR = new[] { ',' };
\r
877 /// Returns a list of keys from the given meta type based on the key list string.
\r
879 /// <param name="keyListString">The key list string.</param>
\r
880 /// <param name="parentType">Type of the parent.</param>
\r
881 /// <returns></returns>
\r
882 private static ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> GetKeys(string keyListString, System.Data.Linq.Mapping.MetaType parentType)
\r
884 if (keyListString != null)
\r
886 var thisKeyList = new List<System.Data.Linq.Mapping.MetaDataMember>();
\r
888 string[] keyNames = keyListString.Split(STRING_SEPERATOR, StringSplitOptions.RemoveEmptyEntries);
\r
890 foreach (string rawKeyName in keyNames)
\r
892 string keyName = rawKeyName.Trim();
\r
894 //TODO: maybe speed the lookup up
\r
895 System.Data.Linq.Mapping.MetaDataMember key = (from dataMember in parentType.PersistentDataMembers
\r
896 where dataMember.Name == keyName
\r
897 select dataMember).SingleOrDefault();
\r
901 string errorMessage = string.Format("Could not find key member '{0}' of key '{1}' on type '{2}'. The key may be wrong or the field or property on '{2}' has changed names.",
\r
902 keyName, keyListString, parentType.Type.Name);
\r
904 throw new InvalidOperationException(errorMessage);
\r
907 thisKeyList.Add(key);
\r
910 return new ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember>(thisKeyList);
\r
912 else //Key is the primary key of this table
\r
914 return parentType.IdentityMembers;
\r
918 public override bool DeleteOnNull { get { return a.DeleteOnNull; } }
\r
919 public override string DeleteRule { get { return a.DeleteRule; } }
\r
920 public override bool IsForeignKey { get { return a.IsForeignKey; } }
\r
922 public override bool IsMany
\r
924 get { throw new NotImplementedException(); }
\r
926 public override bool IsNullable { get { return member.Member.GetMemberType().IsNullable(); } }
\r
927 public override bool IsUnique { get { return a.IsUnique; } }
\r
928 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> OtherKey { get { return other_keys; } }
\r
929 public override bool OtherKeyIsPrimaryKey { get { return OtherKey.All(m => m.IsPrimaryKey); } }
\r
931 public override System.Data.Linq.Mapping.MetaDataMember OtherMember
\r
933 get { throw new NotImplementedException(); }
\r
935 public override System.Data.Linq.Mapping.MetaType OtherType { get { return OtherMember.DeclaringType; } }
\r
936 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaDataMember> ThisKey { get { return these_keys; } }
\r
937 public override bool ThisKeyIsPrimaryKey { get { return ThisKey.All(m => m.IsPrimaryKey); } }
\r
938 public override System.Data.Linq.Mapping.MetaDataMember ThisMember { get { return member; } }
\r
941 abstract class XmlMetaDataMember : System.Data.Linq.Mapping.MetaDataMember
\r
943 internal XmlMetaModel model;
\r
944 internal XmlMetaType type;
\r
945 internal MemberInfo member, storage;
\r
946 System.Data.Linq.Mapping.MetaAccessor member_accessor, storage_accessor;
\r
949 protected XmlMetaDataMember(XmlMetaModel model, XmlMetaType type, string memberName, string storageName, int ordinal)
\r
951 this.model = model;
\r
953 BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
\r
954 if (type.Type.GetMember(memberName, bf).Length == 0)
\r
955 throw new ArgumentException(String.Format("Specified member '{0}' was not found in type '{1}'", memberName, type.Name));
\r
956 if (type.Type.GetMember(storageName, bf).Length == 0)
\r
957 throw new ArgumentException(String.Format("Specified member '{0}' was not found in type '{1}'", storageName, type.Name));
\r
958 this.member = type.Type.GetMember(memberName, bf)[0];
\r
959 this.storage = type.Type.GetMember(storageName, bf)[0];
\r
960 this.ordinal = ordinal;
\r
963 public override bool CanBeNull { get { return member.GetMemberType().IsNullable(); } }
\r
964 public override System.Data.Linq.Mapping.MetaType DeclaringType { get { return type; } }
\r
965 public override bool IsDeferred { get { return false; } }
\r
966 public override bool IsPersistent { get { return true; } }
\r
967 public override MemberInfo Member { get { return member; } }
\r
968 public override System.Data.Linq.Mapping.MetaAccessor MemberAccessor
\r
972 if (member_accessor == null)
\r
973 member_accessor = new XmlMetaAccessor(this, Member);
\r
974 return member_accessor;
\r
977 public override int Ordinal { get { return ordinal; } }
\r
978 public override System.Data.Linq.Mapping.MetaAccessor StorageAccessor
\r
982 if (storage_accessor == null)
\r
983 storage_accessor = new XmlMetaAccessor(this, StorageMember);
\r
984 return storage_accessor;
\r
987 public override MemberInfo StorageMember { get { return storage; } }
\r
988 public override System.Type Type { get { return member.GetMemberType(); } }
\r
990 public override bool IsDeclaredBy(System.Data.Linq.Mapping.MetaType type)
\r
992 return this.type == type;
\r
996 class XmlColumnMetaDataMember : XmlMetaDataMember
\r
1000 public XmlColumnMetaDataMember(XmlMetaModel model, XmlMetaType type, DbmlColumn column, int ordinal)
\r
1001 : base(model, type, column.Member, column.Storage, ordinal)
\r
1006 public override System.Data.Linq.Mapping.MetaAssociation Association { get { return null; } }
\r
1007 public override System.Data.Linq.Mapping.AutoSync AutoSync { get { return (System.Data.Linq.Mapping.AutoSync)c.AutoSync; } }
\r
1008 public override string DbType { get { return c.DbType; } }
\r
1010 public override System.Data.Linq.Mapping.MetaAccessor DeferredSourceAccessor
\r
1012 get { throw new NotImplementedException(); }
\r
1015 public override System.Data.Linq.Mapping.MetaAccessor DeferredValueAccessor
\r
1017 get { throw new NotImplementedException(); }
\r
1020 public override string Expression { get { return c.Expression; } }
\r
1021 public override bool IsAssociation { get { return false; } }
\r
1022 public override bool IsDbGenerated { get { return c.IsDbGenerated; } }
\r
1023 public override bool IsDiscriminator { get { return c.IsDiscriminator; } }
\r
1024 public override bool IsPrimaryKey { get { return c.IsPrimaryKey; } }
\r
1025 public override bool IsVersion { get { return c.IsVersion; } }
\r
1027 public override MethodInfo LoadMethod
\r
1031 throw new NotImplementedException();
\r
1034 public override string MappedName { get { return c.Name; } }
\r
1035 public override string Name { get { return c.Member ?? c.Name; } }
\r
1036 public override System.Data.Linq.Mapping.UpdateCheck UpdateCheck { get { return c.UpdateCheck; } }
\r
1039 class XmlAssociationMetaDataMember : XmlMetaDataMember
\r
1041 DbmlAssociation a;
\r
1042 XmlMetaAssociation ma;
\r
1044 public XmlAssociationMetaDataMember(XmlMetaModel model, XmlMetaType type, DbmlAssociation association, int ordinal)
\r
1045 : base(model, type, association.Member, association.Storage, ordinal)
\r
1047 this.a = association;
\r
1050 public override System.Data.Linq.Mapping.MetaAssociation Association
\r
1055 this.ma = new XmlMetaAssociation(type, this, a);
\r
1059 public override System.Data.Linq.Mapping.AutoSync AutoSync { get { return System.Data.Linq.Mapping.AutoSync.Never; } }
\r
1060 public override string DbType { get { return String.Empty; } }
\r
1062 public override System.Data.Linq.Mapping.MetaAccessor DeferredSourceAccessor
\r
1064 get { throw new NotImplementedException(); }
\r
1067 public override System.Data.Linq.Mapping.MetaAccessor DeferredValueAccessor
\r
1069 get { throw new NotImplementedException(); }
\r
1072 public override string Expression { get { return String.Empty; } }
\r
1073 public override bool IsAssociation { get { return true; } }
\r
1074 public override bool IsDbGenerated { get { return false; } }
\r
1075 public override bool IsDiscriminator { get { return false; } }
\r
1077 public override bool IsPrimaryKey
\r
1079 get { throw new NotImplementedException(); }
\r
1082 public override bool IsVersion
\r
1084 get { throw new NotImplementedException(); }
\r
1087 public override MethodInfo LoadMethod
\r
1091 throw new NotImplementedException();
\r
1094 public override string MappedName { get { return a.Member; } }
\r
1095 public override string Name { get { return a.Name; } }
\r
1096 public override System.Data.Linq.Mapping.UpdateCheck UpdateCheck
\r
1100 throw new NotImplementedException();
\r
1105 class XmlMetaAccessor : System.Data.Linq.Mapping.MetaAccessor
\r
1107 XmlMetaDataMember member;
\r
1108 MemberInfo member_info;
\r
1110 public XmlMetaAccessor(XmlMetaDataMember member, MemberInfo memberInfo)
\r
1112 this.member = member;
\r
1113 this.member_info = memberInfo;
\r
1116 public override System.Type Type
\r
1118 get { return member_info is FieldInfo ? ((FieldInfo)member_info).FieldType : ((PropertyInfo)member_info).PropertyType; }
\r
1122 public override object GetBoxedValue(object instance)
\r
1124 throw new NotImplementedException();
\r
1128 public override void SetBoxedValue(ref object instance, object value)
\r
1130 throw new NotImplementedException();
\r
1134 class XmlMetaFunction : System.Data.Linq.Mapping.MetaFunction
\r
1136 XmlMetaModel model;
\r
1138 MethodInfo method;
\r
1139 ReadOnlyCollection<System.Data.Linq.Mapping.MetaParameter> parameters;
\r
1140 ReadOnlyCollection<System.Data.Linq.Mapping.MetaType> result_types;
\r
1141 System.Data.Linq.Mapping.MetaParameter return_param;
\r
1143 public XmlMetaFunction(XmlMetaModel model, DbmlFunction function)
\r
1145 this.model = model;
\r
1146 this.f = function;
\r
1147 method = model.ContextType.GetMethod(function.Method);
\r
1148 return_param = new XmlMetaParameter(function.Return.DbType, String.Empty, method.ReturnParameter);
\r
1151 public override bool HasMultipleResults { get { return f.ElementTypes.Count > 0; } }
\r
1152 public override bool IsComposable { get { return f.IsComposable; } }
\r
1153 public override string MappedName { get { return f.Name; } }
\r
1154 public override MethodInfo Method { get { return method; } }
\r
1155 public override System.Data.Linq.Mapping.MetaModel Model { get { return model; } }
\r
1156 public override string Name { get { return f.Name; } }
\r
1157 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaParameter> Parameters
\r
1161 if (parameters == null)
\r
1163 var l = new List<System.Data.Linq.Mapping.MetaParameter>();
\r
1165 ParameterInfo[] mparams = method.GetParameters();
\r
1166 foreach (var p in f.Parameters)
\r
1167 l.Add(new XmlMetaParameter(p, mparams[i++]));
\r
1168 parameters = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaParameter>(l);
\r
1170 return parameters;
\r
1173 public override ReadOnlyCollection<System.Data.Linq.Mapping.MetaType> ResultRowTypes
\r
1177 if (result_types == null)
\r
1179 var l = new List<System.Data.Linq.Mapping.MetaType>();
\r
1180 foreach (var p in f.ElementTypes)
\r
1181 l.Add(model.GetMetaType(model.GetTypeFromName(p.Name)));
\r
1182 result_types = new ReadOnlyCollection<System.Data.Linq.Mapping.MetaType>(l.ToArray());
\r
1184 return result_types;
\r
1187 public override System.Data.Linq.Mapping.MetaParameter ReturnParameter { get { return return_param; } }
\r