Лучший подход, который я знаю, должен сделать обновление, сопровождаемое вставкой. "Наверху выбора" необходимо, но это не ужасная нагрузка, так как Вы ищете на первичном ключе, который быстр.
необходимо быть в состоянии изменить ниже операторов с таблицей & имена полей, чтобы сделать то, что Вы хотите.
--first, update any matches
UPDATE DESTINATION_TABLE DT
SET
MY_FIELD1 = (
SELECT MY_FIELD1
FROM SOURCE_TABLE ST
WHERE ST.PRIMARY_KEY = DT.PRIMARY_KEY
)
,MY_FIELD2 = (
SELECT MY_FIELD2
FROM SOURCE_TABLE ST
WHERE ST.PRIMARY_KEY = DT.PRIMARY_KEY
)
WHERE EXISTS(
SELECT ST2.PRIMARY_KEY
FROM
SOURCE_TABLE ST2
,DESTINATION_TABLE DT2
WHERE ST2.PRIMARY_KEY = DT2.PRIMARY_KEY
);
--second, insert any non-matches
INSERT INTO DESTINATION_TABLE(
MY_FIELD1
,MY_FIELD2
)
SELECT
ST.MY_FIELD1
,NULL AS MY_FIELD2 --insert NULL into this field
FROM
SOURCE_TABLE ST
WHERE NOT EXISTS(
SELECT DT2.PRIMARY_KEY
FROM DESTINATION_TABLE DT2
WHERE DT2.PRIMARY_KEY = ST.PRIMARY_KEY
);
Это хорошо для меня компилируется:
interface I1 { int NumberOne { get; set; } }
interface I2 { int NumberTwo { get; set; } }
static void DoSomething<T>(T item) where T:I1,I2
{
Console.WriteLine(item.NumberOne);
Console.WriteLine(item.NumberTwo);
}
Итак, синтаксис кажется прекрасным ... возможно, что-то еще вызывает проблема.
Интерфейс 1 и интерфейс 2 являются производными от одного и того же базового интерфейса. Пример:
public static void DoSomething<T>() where T : ICommon
{
//...
}
public interface IInterface1 : ICommon
{}
public interface IInterface2 : ICommon
{ }
public interface ICommon
{ }
Преимущество этого способа состоит в том, что вам не нужно постоянно обновлять определение DoSomething () каждый раз, когда вы добавляете новый интерфейс, наследуемый от ICommon.
Изменить: если у вас нет контроль над интерфейсами, у вас есть несколько вариантов. Вот одна вещь, которую вы могли бы сделать ...
protected static class DoSomethingServer<T1> where T1 : class
{
//Define your allowed types here
private static List<Type> AllowedTypes = new List<Type> {
typeof(IInterface1),
typeof(IInterface2)
};
public static MethodInvoker DoSomething()
{
//Perform type check
if (AllowedTypes.Contains(typeof(T1)))
{
return DoSomethingImplementation;
}
else
{
throw new ApplicationException("Wrong Type");
}
}
private static void DoSomethingImplementation()
{
//Actual DoSomething work here
//This is guaranteed to only be called if <T> is in the allowed type list
}
}
Использовать как таковой:
DoSomethingServer<IInterface1>.DoSomething();
К сожалению, это снижает безопасность типов во время компиляции, и это приведет к сбою во время выполнения, только если вы попытаетесь ввести неправильный тип. Очевидно, это далеко не идеально.
Если вы имеете в виду, что параметр может быть либо реализацией I1, либо реализацией I2, и они не связаны между собой типами, тогда вы не можете написать одну группу методов (т.е. перегрузки с тем же именем метода ) для обработки обоих типов.
Вы даже не можете сказать (заимствуя из nader!):
interface I1 { int NumberOne { get; set; } }
interface I2 { int NumberTwo { get; set; } }
static void DoSomething<T>(T item) where T : I1
{
Console.WriteLine(item.NumberOne);
}
static void DoSomething<T>(T item) where T : I2
{
Console.WriteLine(item.NumberTwo);
}
static void DoSomething<T>(T item) where T : I1, I2
{
Console.WriteLine(item.NumberOne);
Console.WriteLine(item.NumberTwo);
}
Это дало бы компилятору возможность обрабатывать все возможности без двусмысленности. Но чтобы помочь с управлением версиями, C # пытается избежать ситуаций, когда добавление / удаление метода изменит применимость другого метода.
Вам необходимо написать два метода с разными именами для обработки двух интерфейсов.
один из способов - создать дополнительный интерфейс, который расширяет оба, Interface1 и 2. затем вы помещаете этот интерфейс вместо другого 2.
это один из способов сделать это в java; Если я правильно помню, это должно работать и в C #
, надеюсь, что это поможет.
С уважением, Тоби: P
public interface IInterfaceBase
{
}
public interface IInterface1 : IInterfaceBase
{
...
}
public interface IInterface2 : IInterfaceBase
{
...
}
public static void DoSomething<T>() where T: IInterfaceBase
{
}
Если вы хотите, чтобы T был IInterface1 или IInterface2, используйте приведенный выше код
Основываясь на том, что сказал Эрвикер ... имена - не единственный путь. Вы также можете изменять сигнатуры методов ...
public interface I1 { int NumberOne { get; set; } }
public interface I2 { int NumberTwo { get; set; } }
public static class EitherInterface
{
public static void DoSomething<T>(I1 item) where T : I1
{
Console.WriteLine("I1 : {0}", item.NumberOne);
}
public static void DoSomething<T>(I2 item) where T : I2
{
Console.WriteLine("I2 : {0}", item.NumberTwo);
}
}
Что при тестировании следующим образом:
public class Class12 : I1, I2
{
public int NumberOne { get; set; }
public int NumberTwo { get; set; }
}
public class TestClass
{
public void Test1()
{
Class12 z = new Class12();
EitherInterface.DoSomething<Class12>((I1)z);
EitherInterface.DoSomething<Class12>((I2)z);
}
}
Дает следующий результат:
I1 : 0
I2 : 0
Это соответствует цели раскрытия единственного имени метода для вызывающего, но не помогает вам, поскольку вы не используете параметры.